diff options
Diffstat (limited to 'clang/lib/Frontend')
-rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/CMakeLists.txt | 6 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Frontend/GeneratePCH.cpp | 64 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReader.cpp | 3857 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReaderDecl.cpp | 1600 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReaderStmt.cpp | 1775 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriter.cpp | 3094 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriterDecl.cpp | 1174 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriterStmt.cpp | 1370 |
12 files changed, 5 insertions, 12945 deletions
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 428647f03f4..019d25c131f 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/ASTUnit.h" -#include "clang/Frontend/PCHWriter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclVisitor.h" @@ -26,7 +25,8 @@ #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendOptions.h" -#include "clang/Frontend/PCHReader.h" +#include "clang/Serialization/PCHReader.h" +#include "clang/Serialization/PCHWriter.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetOptions.h" diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index a3fd17fc8c2..fa20aff9657 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -20,12 +20,6 @@ add_clang_library(clangFrontend InitHeaderSearch.cpp InitPreprocessor.cpp LangStandards.cpp - PCHReader.cpp - PCHReaderDecl.cpp - PCHReaderStmt.cpp - PCHWriter.cpp - PCHWriterDecl.cpp - PCHWriterStmt.cpp PrintPreprocessedOutput.cpp StmtXML.cpp TextDiagnosticBuffer.cpp diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 8e1dbcb9d24..aaa67804cef 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -21,11 +21,11 @@ #include "clang/Lex/PTHManager.h" #include "clang/Frontend/ChainedDiagnosticClient.h" #include "clang/Frontend/FrontendAction.h" -#include "clang/Frontend/PCHReader.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/VerifyDiagnosticsClient.h" #include "clang/Frontend/Utils.h" +#include "clang/Serialization/PCHReader.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "llvm/LLVMContext.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 82cd75d18ab..68b384f48c2 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -18,7 +18,7 @@ #include "clang/Driver/Option.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/LangStandard.h" -#include "clang/Frontend/PCHReader.h" +#include "clang/Serialization/PCHReader.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 0a03ab4c847..8599efb95ee 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -17,8 +17,8 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/PCHWriter.h" #include "clang/Frontend/Utils.h" +#include "clang/Serialization/PCHWriter.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang/lib/Frontend/GeneratePCH.cpp b/clang/lib/Frontend/GeneratePCH.cpp deleted file mode 100644 index 33f5ef56ae3..00000000000 --- a/clang/lib/Frontend/GeneratePCH.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//===--- GeneratePCH.cpp - AST Consumer for PCH Generation ------*- 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 CreatePCHGenerate function, which creates an -// ASTConsume that generates a PCH file. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/ASTConsumers.h" -#include "clang/Frontend/PCHWriter.h" -#include "clang/Sema/SemaConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Basic/FileManager.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/raw_ostream.h" -#include <string> - -using namespace clang; - -PCHGenerator::PCHGenerator(const Preprocessor &PP, - bool Chaining, - const char *isysroot, - llvm::raw_ostream *OS) - : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), - StatCalls(0), Stream(Buffer), Writer(Stream) { - - // Install a stat() listener to keep track of all of the stat() - // calls. - StatCalls = new MemorizeStatCalls; - // If we have a chain, we want new stat calls only, so install the memorizer - // *after* the already installed PCHReader's stat cache. - PP.getFileManager().addStatCache(StatCalls, - /*AtBeginning=*/!Chaining); -} - -void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { - if (PP.getDiagnostics().hasErrorOccurred()) - return; - - // Emit the PCH file - assert(SemaPtr && "No Sema?"); - Writer.WritePCH(*SemaPtr, StatCalls, isysroot); - - // Write the generated bitstream to "Out". - Out->write((char *)&Buffer.front(), Buffer.size()); - - // Make sure it hits disk now. - Out->flush(); - - // Free up some memory, in case the process is kept alive. - Buffer.clear(); -} - -PCHDeserializationListener *PCHGenerator::GetPCHDeserializationListener() { - return &Writer; -} diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp deleted file mode 100644 index 94917707975..00000000000 --- a/clang/lib/Frontend/PCHReader.cpp +++ /dev/null @@ -1,3857 +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 "clang/Sema/Sema.h" -#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(); - (void) RN; - 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, bool DisableValidation) - : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), - SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), - Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation), - NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), - TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0), - NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0), - NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0), - TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0), - TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), - TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) { - RelocatablePCH = false; -} - -PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags, const char *isysroot, - bool DisableValidation) - : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), - Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0), - isysroot(isysroot), DisableValidation(DisableValidation), NumStatHits(0), - NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0), - NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0), - TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), - NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0), - NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), - NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), - NumCurrentElementsDeserializing(0) { - RelocatablePCH = false; -} - -PCHReader::~PCHReader() { - for (unsigned i = 0, e = Chain.size(); i != e; ++i) - delete Chain[e - i - 1]; -} - -PCHReader::PerFileData::PerFileData() - : StatCache(0), LocalNumSLocEntries(0), LocalNumTypes(0), TypeOffsets(0), - LocalNumDecls(0), DeclOffsets(0), LocalNumIdentifiers(0), - IdentifierOffsets(0), IdentifierTableData(0), IdentifierLookupTable(0), - LocalNumMacroDefinitions(0), MacroDefinitionOffsets(0), - NumPreallocatedPreprocessingEntities(0), SelectorLookupTable(0), - SelectorLookupTableData(0), SelectorOffsets(0), LocalNumSelectors(0) -{} - -void -PCHReader::setDeserializationListener(PCHDeserializationListener *Listener) { - DeserializationListener = Listener; - if (DeserializationListener) - DeserializationListener->SetReader(this); -} - - -namespace { -class PCHSelectorLookupTrait { - PCHReader &Reader; - -public: - struct data_type { - pch::SelectorID ID; - ObjCMethodList Instance, Factory; - }; - - typedef Selector external_key_type; - typedef external_key_type internal_key_type; - - explicit PCHSelectorLookupTrait(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; - - data_type Result; - - Result.ID = ReadUnalignedLE32(d); - unsigned NumInstanceMethods = ReadUnalignedLE16(d); - unsigned NumFactoryMethods = ReadUnalignedLE16(d); - - // Load instance methods - ObjCMethodList *Prev = 0; - for (unsigned I = 0; I != NumInstanceMethods; ++I) { - ObjCMethodDecl *Method - = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (!Result.Instance.Method) { - // This is the first method, which is the easy case. - Result.Instance.Method = Method; - Prev = &Result.Instance; - 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.Factory.Method) { - // This is the first method, which is the easy case. - Result.Factory.Method = Method; - Prev = &Result.Factory; - 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<PCHSelectorLookupTrait> - PCHSelectorLookupTable; - -namespace { -class PCHIdentifierLookupTrait { - PCHReader &Reader; - llvm::BitstreamCursor &Stream; - - // 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; - - PCHIdentifierLookupTrait(PCHReader &Reader, llvm::BitstreamCursor &Stream, - IdentifierInfo *II = 0) - : Reader(Reader), Stream(Stream), 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 uninteresting identifiers, just build the IdentifierInfo - // and associate it with the persistent ID. - IdentifierInfo *II = KnownII; - if (!II) - II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second); - Reader.SetIdentifierInfo(ID, II); - II->setIsFromPCH(); - return II; - } - - unsigned Bits = ReadUnalignedLE16(d); - bool CPlusPlusOperatorKeyword = Bits & 0x01; - Bits >>= 1; - bool HasRevertedTokenIDToIdentifier = 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().getOwn(k.first, k.first + k.second); - Reader.SetIdentifierInfo(ID, II); - - // Set or check the various bits in the IdentifierInfo structure. - // Token IDs are read-only. - if (HasRevertedTokenIDToIdentifier) - II->RevertTokenIDToIdentifier(); - 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(Stream, 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); - } - - II->setIsFromPCH(); - 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 a source manager block -PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock(PerFileData &F) { - using namespace SrcMgr; - - llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor; - - // 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 = F.Stream; - - // The stream itself is going to skip over the source manager block. - if (F.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 Get a cursor that's correctly positioned for reading the source -/// location entry with the given ID. -llvm::BitstreamCursor &PCHReader::SLocCursorForID(unsigned ID) { - assert(ID != 0 && ID <= TotalNumSLocEntries && - "SLocCursorForID should only be called for real IDs."); - - ID -= 1; - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - F = Chain[N - I - 1]; - if (ID < F->LocalNumSLocEntries) - break; - ID -= F->LocalNumSLocEntries; - } - assert(F && F->LocalNumSLocEntries > ID && "Chain corrupted"); - - F->SLocEntryCursor.JumpToBit(F->SLocOffsets[ID]); - return F->SLocEntryCursor; -} - -/// \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; - } - - llvm::BitstreamCursor &SLocEntryCursor = SLocCursorForID(ID); - - ++NumSLocEntriesRead; - 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 (!DisableValidation && - ((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(llvm::BitstreamCursor &Stream, 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); - MI->setIsFromPCH(); - - 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() { - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - llvm::BitstreamCursor &MacroCursor = Chain[N - I - 1]->MacroCursor; - - // If there was no preprocessor block, skip this file. - if (!MacroCursor.getBitStreamReader()) - continue; - - 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; - } - break; - } - - 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(Chain[N - I - 1]->Stream, Cursor.GetCurrentBitNo()); - break; - } - } - } -} - -MacroDefinition *PCHReader::getMacroDefinition(pch::IdentID ID) { - if (ID == 0 || ID >= MacroDefinitionsLoaded.size()) - return 0; - - if (!MacroDefinitionsLoaded[ID]) { - unsigned Index = ID; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - if (Index < F.LocalNumMacroDefinitions) { - ReadMacroRecord(F.Stream, F.MacroDefinitionOffsets[Index]); - break; - } - Index -= F.LocalNumMacroDefinitions; - } - assert(MacroDefinitionsLoaded[ID] && "Broken chain"); - } - - 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(PerFileData &F) { - llvm::BitstreamCursor &Stream = F.Stream; - - 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; - bool First = true; - 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. - F.DeclsCursor = Stream; - if (Stream.SkipBlock() || // Skip with the main cursor. - // Read the abbrevs. - ReadBlockAbbrevs(F.DeclsCursor, pch::DECLTYPES_BLOCK_ID)) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - - case pch::PREPROCESSOR_BLOCK_ID: - F.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(F)) { - case Success: - break; - - case Failure: - Error("malformed source manager block in PCH file"); - return Failure; - - case IgnorePCH: - return IgnorePCH; - } - break; - } - First = false; - 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::METADATA: { - if (Record[0] != pch::VERSION_MAJOR && !DisableValidation) { - 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::CHAINED_METADATA: { - if (!First) { - Error("CHAINED_METADATA is not first record in block"); - return Failure; - } - if (Record[0] != pch::VERSION_MAJOR && !DisableValidation) { - Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old - : diag::warn_pch_version_too_new); - return IgnorePCH; - } - - // Load the chained file. - switch(ReadPCHCore(llvm::StringRef(BlobStart, BlobLen))) { - case Failure: return Failure; - // If we have to ignore the dependency, we'll have to ignore this too. - case IgnorePCH: return IgnorePCH; - case Success: break; - } - break; - } - - case pch::TYPE_OFFSET: - if (F.LocalNumTypes != 0) { - Error("duplicate TYPE_OFFSET record in PCH file"); - return Failure; - } - F.TypeOffsets = (const uint32_t *)BlobStart; - F.LocalNumTypes = Record[0]; - break; - - case pch::DECL_OFFSET: - if (F.LocalNumDecls != 0) { - Error("duplicate DECL_OFFSET record in PCH file"); - return Failure; - } - F.DeclOffsets = (const uint32_t *)BlobStart; - F.LocalNumDecls = Record[0]; - break; - - case pch::TU_UPDATE_LEXICAL: { - DeclContextInfo Info = { - /* No visible information */ 0, 0, - reinterpret_cast<const pch::DeclID *>(BlobStart), - BlobLen / sizeof(pch::DeclID) - }; - DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info); - break; - } - - case pch::REDECLS_UPDATE_LATEST: { - assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs"); - for (unsigned i = 0, e = Record.size(); i < e; i += 2) { - pch::DeclID First = Record[i], Latest = Record[i+1]; - assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() || - Latest > FirstLatestDeclIDs[First]) && - "The new latest is supposed to come after the previous latest"); - FirstLatestDeclIDs[First] = Latest; - } - break; - } - - case pch::LANGUAGE_OPTIONS: - if (ParseLanguageOptions(Record) && !DisableValidation) - return IgnorePCH; - break; - - case pch::IDENTIFIER_TABLE: - F.IdentifierTableData = BlobStart; - if (Record[0]) { - F.IdentifierLookupTable - = PCHIdentifierLookupTable::Create( - (const unsigned char *)F.IdentifierTableData + Record[0], - (const unsigned char *)F.IdentifierTableData, - PCHIdentifierLookupTrait(*this, F.Stream)); - if (PP) - PP->getIdentifierTable().setExternalIdentifierLookup(this); - } - break; - - case pch::IDENTIFIER_OFFSET: - if (F.LocalNumIdentifiers != 0) { - Error("duplicate IDENTIFIER_OFFSET record in PCH file"); - return Failure; - } - F.IdentifierOffsets = (const uint32_t *)BlobStart; - F.LocalNumIdentifiers = Record[0]; - break; - - case pch::EXTERNAL_DEFINITIONS: - // Optimization for the first block. - if (ExternalDefinitions.empty()) - ExternalDefinitions.swap(Record); - else - ExternalDefinitions.insert(ExternalDefinitions.end(), - Record.begin(), Record.end()); - break; - - case pch::SPECIAL_TYPES: - // Optimization for the first block - if (SpecialTypes.empty()) - SpecialTypes.swap(Record); - else - SpecialTypes.insert(SpecialTypes.end(), Record.begin(), Record.end()); - break; - - case pch::STATISTICS: - TotalNumStatements += Record[0]; - TotalNumMacros += Record[1]; - TotalLexicalDeclContexts += Record[2]; - TotalVisibleDeclContexts += Record[3]; - break; - - case pch::TENTATIVE_DEFINITIONS: - // Optimization for the first block. - if (TentativeDefinitions.empty()) - TentativeDefinitions.swap(Record); - else - TentativeDefinitions.insert(TentativeDefinitions.end(), - Record.begin(), Record.end()); - break; - - case pch::UNUSED_FILESCOPED_DECLS: - // Optimization for the first block. - if (UnusedFileScopedDecls.empty()) - UnusedFileScopedDecls.swap(Record); - else - UnusedFileScopedDecls.insert(UnusedFileScopedDecls.end(), - Record.begin(), Record.end()); - break; - - case pch::WEAK_UNDECLARED_IDENTIFIERS: - // Later blocks overwrite earlier ones. - WeakUndeclaredIdentifiers.swap(Record); - break; - - case pch::LOCALLY_SCOPED_EXTERNAL_DECLS: - // Optimization for the first block. - if (LocallyScopedExternalDecls.empty()) - LocallyScopedExternalDecls.swap(Record); - else - LocallyScopedExternalDecls.insert(LocallyScopedExternalDecls.end(), - Record.begin(), Record.end()); - break; - - case pch::SELECTOR_OFFSETS: - F.SelectorOffsets = (const uint32_t *)BlobStart; - F.LocalNumSelectors = Record[0]; - break; - - case pch::METHOD_POOL: - F.SelectorLookupTableData = (const unsigned char *)BlobStart; - if (Record[0]) - F.SelectorLookupTable - = PCHSelectorLookupTable::Create( - F.SelectorLookupTableData + Record[0], - F.SelectorLookupTableData, - PCHSelectorLookupTrait(*this)); - TotalNumMethodPoolEntries += Record[1]; - break; - - case pch::REFERENCED_SELECTOR_POOL: { - ReferencedSelectorsData.insert(ReferencedSelectorsData.end(), - Record.begin(), Record.end()); - break; - } - - case pch::PP_COUNTER_VALUE: - if (!Record.empty() && Listener) - Listener->ReadCounter(Record[0]); - break; - - case pch::SOURCE_LOCATION_OFFSETS: - F.SLocOffsets = (const uint32_t *)BlobStart; - F.LocalNumSLocEntries = Record[0]; - // We cannot delay this until all PCHs are loaded, because then source - // location preloads would also have to be delayed. - TotalNumSLocEntries += F.LocalNumSLocEntries; - 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); - F.StatCache = MyStatCache; - break; - } - - case pch::EXT_VECTOR_DECLS: - // Optimization for the first block. - if (ExtVectorDecls.empty()) - ExtVectorDecls.swap(Record); - else - ExtVectorDecls.insert(ExtVectorDecls.end(), - Record.begin(), Record.end()); - break; - - case pch::VTABLE_USES: - // Later tables overwrite earlier ones. - VTableUses.swap(Record); - break; - - case pch::DYNAMIC_CLASSES: - // Optimization for the first block. - if (DynamicClasses.empty()) - DynamicClasses.swap(Record); - else - DynamicClasses.insert(DynamicClasses.end(), - Record.begin(), Record.end()); - break; - - case pch::PENDING_IMPLICIT_INSTANTIATIONS: - // Optimization for the first block. - if (PendingImplicitInstantiations.empty()) - PendingImplicitInstantiations.swap(Record); - else - PendingImplicitInstantiations.insert( - PendingImplicitInstantiations.end(), Record.begin(), Record.end()); - break; - - case pch::SEMA_DECL_REFS: - // Later tables overwrite earlier ones. - SemaDeclRefs.swap(Record); - break; - - case pch::ORIGINAL_FILE_NAME: - // The primary PCH will be the last to get here, so it will be the one - // that's used. - 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 && !DisableValidation) { - Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch; - return IgnorePCH; - } - break; - } - - case pch::MACRO_DEFINITION_OFFSETS: - F.MacroDefinitionOffsets = (const uint32_t *)BlobStart; - F.NumPreallocatedPreprocessingEntities = Record[0]; - F.LocalNumMacroDefinitions = Record[1]; - break; - - case pch::DECL_REPLACEMENTS: { - if (Record.size() % 2 != 0) { - Error("invalid DECL_REPLACEMENTS block in PCH file"); - return Failure; - } - for (unsigned I = 0, N = Record.size(); I != N; I += 2) - ReplacedDecls[static_cast<pch::DeclID>(Record[I])] = - std::make_pair(&F, Record[I+1]); - break; - } - } - First = false; - } - Error("premature end of bitstream in PCH file"); - return Failure; -} - -PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { - switch(ReadPCHCore(FileName)) { - case Failure: return Failure; - case IgnorePCH: return IgnorePCH; - case Success: break; - } - - // Here comes stuff that we only do once the entire chain is loaded. - - // Allocate space for loaded identifiers, decls and types. - unsigned TotalNumIdentifiers = 0, TotalNumTypes = 0, TotalNumDecls = 0, - TotalNumPreallocatedPreprocessingEntities = 0, TotalNumMacroDefs = 0, - TotalNumSelectors = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - TotalNumIdentifiers += Chain[I]->LocalNumIdentifiers; - TotalNumTypes += Chain[I]->LocalNumTypes; - TotalNumDecls += Chain[I]->LocalNumDecls; - TotalNumPreallocatedPreprocessingEntities += - Chain[I]->NumPreallocatedPreprocessingEntities; - TotalNumMacroDefs += Chain[I]->LocalNumMacroDefinitions; - TotalNumSelectors += Chain[I]->LocalNumSelectors; - } - IdentifiersLoaded.resize(TotalNumIdentifiers); - TypesLoaded.resize(TotalNumTypes); - DeclsLoaded.resize(TotalNumDecls); - MacroDefinitionsLoaded.resize(TotalNumMacroDefs); - if (PP) { - if (TotalNumIdentifiers > 0) - PP->getHeaderSearchInfo().SetExternalLookup(this); - if (TotalNumPreallocatedPreprocessingEntities > 0) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); - PP->getPreprocessingRecord()->SetExternalSource(*this, - TotalNumPreallocatedPreprocessingEntities); - } - } - SelectorsLoaded.resize(TotalNumSelectors); - - // Check the predefines buffers. - if (!DisableValidation && 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); - // We need to search the tables in all files. - for (unsigned J = 0, M = Chain.size(); J != M; ++J) { - PCHIdentifierLookupTable *IdTable - = (PCHIdentifierLookupTable *)Chain[J]->IdentifierLookupTable; - // Not all PCH files necessarily have identifier tables, only the useful - // ones. - if (!IdTable) - continue; - for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { - IdentifierInfo *II = Identifiers[I]; - // Look in the on-disk hash tables for an entry for this identifier - PCHIdentifierLookupTrait Info(*this, Chain[J]->Stream, 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; -} - -PCHReader::PCHReadResult PCHReader::ReadPCHCore(llvm::StringRef FileName) { - Chain.push_back(new PerFileData()); - PerFileData &F = *Chain.back(); - - // Set the PCH file name. - F.FileName = FileName; - - // Open the PCH file. - // - // FIXME: This shouldn't be here, we should just take a raw_ostream. - std::string ErrStr; - F.Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr)); - if (!F.Buffer) { - Error(ErrStr.c_str()); - return IgnorePCH; - } - - // Initialize the stream - F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(), - (const unsigned char *)F.Buffer->getBufferEnd()); - llvm::BitstreamCursor &Stream = F.Stream; - Stream.init(F.StreamFile); - F.SizeInBits = F.Buffer->getBufferSize() * 8; - - // 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(F)) { - 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 (F.StatCache) - FileMgr.removeStatCache((PCHStatCache*)F.StatCache); - - return IgnorePCH; - } - break; - default: - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - } - } - - return Success; -} - -void PCHReader::setPreprocessor(Preprocessor &pp) { - PP = &pp; - - unsigned TotalNum = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) - TotalNum += Chain[I]->NumPreallocatedPreprocessingEntities; - if (TotalNum) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); - PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNum); - } -} - -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 Get the correct cursor and offset for loading a type. -PCHReader::RecordLocation PCHReader::TypeCursorForIndex(unsigned Index) { - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - F = Chain[N - I - 1]; - if (Index < F->LocalNumTypes) - break; - Index -= F->LocalNumTypes; - } - assert(F && F->LocalNumTypes > Index && "Broken chain"); - return RecordLocation(&F->DeclsCursor, F->TypeOffsets[Index]); -} - -/// \brief Read and return the type with the given index.. -/// -/// The index is the type ID, shifted and minus the number of predefs. This -/// routine actually reads the record corresponding to the type at the given -/// location. It is a helper routine for GetType, which deals with reading type -/// IDs. -QualType PCHReader::ReadTypeRecord(unsigned Index) { - RecordLocation Loc = TypeCursorForIndex(Index); - llvm::BitstreamCursor &DeclsCursor = *Loc.first; - - // 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. - Deserializing AType(this); - - DeclsCursor.JumpToBit(Loc.second); - 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(DeclsCursor), - 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(DeclsCursor)); - - 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(DeclsCursor)); - - 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(DeclsCursor, 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(DeclsCursor); - 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, DeclsCursor, 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; - llvm::BitstreamCursor &DeclsCursor; - const PCHReader::RecordData &Record; - unsigned &Idx; - -public: - TypeLocReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor, - const PCHReader::RecordData &Record, unsigned &Idx) - : Reader(Reader), DeclsCursor(Cursor), 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(DeclsCursor)); - 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(DeclsCursor, 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(), - DeclsCursor, 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(), - DeclsCursor, 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(llvm::BitstreamCursor &DeclsCursor, - const RecordData &Record, - unsigned &Idx) { - QualType InfoTy = GetType(Record[Idx++]); - if (InfoTy.isNull()) - return 0; - - TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy); - TypeLocReader TLR(*this, DeclsCursor, 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(Index); - TypesLoaded[Index]->setFromPCH(); - if (DeserializationListener) - DeserializationListener->TypeRead(ID >> Qualifiers::FastWidth, - TypesLoaded[Index]); - } - - return TypesLoaded[Index].withFastQualifiers(FastQuals); -} - -TemplateArgumentLocInfo -PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, - llvm::BitstreamCursor &DeclsCursor, - const RecordData &Record, - unsigned &Index) { - switch (Kind) { - case TemplateArgument::Expression: - return ReadExpr(DeclsCursor); - case TemplateArgument::Type: - return GetTypeSourceInfo(DeclsCursor, 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(llvm::BitstreamCursor &DeclsCursor, - const RecordData &Record, unsigned &Index) { - TemplateArgument Arg = ReadTemplateArgument(DeclsCursor, Record, Index); - - if (Arg.getKind() == TemplateArgument::Expression) { - if (Record[Index++]) // bool InfoHasSameExpr. - return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr())); - } - return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(), - DeclsCursor, - Record, Index)); -} - -Decl *PCHReader::GetExternalDecl(uint32_t ID) { - return GetDecl(ID); -} - -TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() { - if (!DeclsLoaded[0]) { - ReadDeclRecord(0, 0); - if (DeserializationListener) - DeserializationListener->DeclRead(1, 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(Index, ID); - 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) { - // Offset here is a global offset across the entire chain. - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - if (Offset < F.SizeInBits) { - // Since we know that this statement is part of a decl, make sure to use - // the decl cursor to read it. - F.DeclsCursor.JumpToBit(Offset); - return ReadStmtFromStream(F.DeclsCursor); - } - Offset -= F.SizeInBits; - } - llvm_unreachable("Broken chain"); -} - -bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC, - llvm::SmallVectorImpl<Decl*> &Decls) { - assert(DC->hasExternalLexicalStorage() && - "DeclContext has no lexical decls in storage"); - - // There might be lexical decls in multiple parts of the chain, for the TU - // at least. - DeclContextInfos &Infos = DeclContextOffsets[DC]; - for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end(); - I != E; ++I) { - // IDs can be 0 if this context doesn't contain declarations. - if (!I->LexicalDecls) - continue; - - // Load all of the declaration IDs - for (const pch::DeclID *ID = I->LexicalDecls, - *IDE = ID + I->NumLexicalDecls; - ID != IDE; ++ID) - Decls.push_back(GetDecl(*ID)); - } - - ++NumLexicalDeclContextsRead; - return false; -} - -DeclContext::lookup_result -PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) { - assert(DC->hasExternalVisibleStorage() && - "DeclContext has no visible decls in storage"); - - llvm::SmallVector<VisibleDeclaration, 64> Decls; - // There might be lexical decls in multiple parts of the chain, for the TU - // and namespaces. - DeclContextInfos &Infos = DeclContextOffsets[DC]; - for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end(); - I != E; ++I) { - uint64_t Offset = I->OffsetToVisibleDecls; - if (Offset == 0) - continue; - - llvm::BitstreamCursor &DeclsCursor = *I->Stream; - - // 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()); - } - - if (Record.empty()) - continue; - - 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 J = 0; J < Size; ++J) - 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->HandleInterestingDecl(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 (!SelectorsLoaded.empty()) - std::fprintf(stderr, " %u/%u selectors read (%f%%)\n", - NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(), - ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 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 (TotalNumMethodPoolEntries) { - std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n", - NumMethodPoolEntriesRead, TotalNumMethodPoolEntries, - ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries - * 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. - if (SemaObj->TUScope) { - 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 file scoped decls, deserialize them and add to - // Sema's list of unused file scoped decls. - for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) { - DeclaratorDecl *D = cast<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I])); - SemaObj->UnusedFileScopedDecls.push_back(D); - } - - // If there were any weak undeclared identifiers, deserialize them and add to - // Sema's list of weak undeclared identifiers. - if (!WeakUndeclaredIdentifiers.empty()) { - unsigned Idx = 0; - for (unsigned I = 0, N = WeakUndeclaredIdentifiers[Idx++]; I != N; ++I) { - IdentifierInfo *WeakId = GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx); - IdentifierInfo *AliasId=GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx); - SourceLocation Loc = ReadSourceLocation(WeakUndeclaredIdentifiers, Idx); - bool Used = WeakUndeclaredIdentifiers[Idx++]; - Sema::WeakInfo WI(AliasId, Loc); - WI.setUsed(Used); - SemaObj->WeakUndeclaredIdentifiers.insert(std::make_pair(WeakId, WI)); - } - } - - // 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. - if (!VTableUses.empty()) { - 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]))); - - // If there were any pending implicit instantiations, deserialize them - // and add them to Sema's queue of such instantiations. - assert(PendingImplicitInstantiations.size() % 2 == 0 && - "Expected pairs of entries"); - for (unsigned Idx = 0, N = PendingImplicitInstantiations.size(); Idx < N;) { - ValueDecl *D=cast<ValueDecl>(GetDecl(PendingImplicitInstantiations[Idx++])); - SourceLocation Loc = ReadSourceLocation(PendingImplicitInstantiations, Idx); - SemaObj->PendingImplicitInstantiations.push_back(std::make_pair(D, Loc)); - } - - // Load the offsets of the declarations that Sema references. - // They will be lazily deserialized when needed. - if (!SemaDeclRefs.empty()) { - assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!"); - SemaObj->StdNamespace = SemaDeclRefs[0]; - SemaObj->StdBadAlloc = SemaDeclRefs[1]; - } - - // If there are @selector references added them to its pool. This is for - // implementation of -Wselector. - if (!ReferencedSelectorsData.empty()) { - unsigned int DataSize = ReferencedSelectorsData.size()-1; - unsigned I = 0; - while (I < DataSize) { - Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]); - SourceLocation SelLoc = - SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]); - SemaObj->ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); - } - } -} - -IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) { - // Try to find this name within our on-disk hash tables. We start with the - // most recent one, since that one contains the most up-to-date info. - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PCHIdentifierLookupTable *IdTable - = (PCHIdentifierLookupTable *)Chain[I]->IdentifierLookupTable; - if (!IdTable) - continue; - std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart); - PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key); - if (Pos == IdTable->end()) - continue; - - // Dereferencing the iterator has the effect of building the - // IdentifierInfo node and populating it with the various - // declarations it needs. - return *Pos; - } - return 0; -} - -std::pair<ObjCMethodList, ObjCMethodList> -PCHReader::ReadMethodPool(Selector Sel) { - // Find this selector in a hash table. We want to find the most recent entry. - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[I]; - if (!F.SelectorLookupTable) - continue; - - PCHSelectorLookupTable *PoolTable - = (PCHSelectorLookupTable*)F.SelectorLookupTable; - PCHSelectorLookupTable::iterator Pos = PoolTable->find(Sel); - if (Pos != PoolTable->end()) { - ++NumSelectorsRead; - // FIXME: Not quite happy with the statistics here. We probably should - // disable this tracking when called via LoadSelector. - // Also, should entries without methods count as misses? - ++NumMethodPoolEntriesRead; - PCHSelectorLookupTrait::data_type Data = *Pos; - if (DeserializationListener) - DeserializationListener->SelectorRead(Data.ID, Sel); - return std::make_pair(Data.Instance, Data.Factory); - } - } - - ++NumMethodPoolMisses; - return std::pair<ObjCMethodList, ObjCMethodList>(); -} - -void PCHReader::LoadSelector(Selector Sel) { - // It would be complicated to avoid reading the methods anyway. So don't. - ReadMethodPool(Sel); -} - -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; - if (DeserializationListener) - DeserializationListener->IdentifierRead(ID, 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 (NumCurrentElementsDeserializing && !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) { - if (SemaObj->TUScope) { - // 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 (IdentifiersLoaded.empty()) { - Error("no identifier table in PCH file"); - return 0; - } - - assert(PP && "Forgot to set Preprocessor ?"); - ID -= 1; - if (!IdentifiersLoaded[ID]) { - unsigned Index = ID; - const char *Str = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData *F = Chain[N - I - 1]; - if (Index < F->LocalNumIdentifiers) { - uint32_t Offset = F->IdentifierOffsets[Index]; - Str = F->IdentifierTableData + Offset; - break; - } - Index -= F->LocalNumIdentifiers; - } - assert(Str && "Broken Chain"); - - // 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] - = &PP->getIdentifierTable().get(Str, StrLen); - if (DeserializationListener) - DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]); - } - - return IdentifiersLoaded[ID]; -} - -void PCHReader::ReadSLocEntry(unsigned ID) { - ReadSLocEntryRecord(ID); -} - -Selector PCHReader::DecodeSelector(unsigned ID) { - if (ID == 0) - return Selector(); - - if (ID > SelectorsLoaded.size()) { - Error("selector ID out of range in PCH file"); - return Selector(); - } - - if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) { - // Load this selector from the selector table. - unsigned Idx = ID - 1; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - PerFileData &F = *Chain[N - I - 1]; - if (Idx < F.LocalNumSelectors) { - PCHSelectorLookupTrait Trait(*this); - SelectorsLoaded[ID - 1] = - Trait.ReadKey(F.SelectorLookupTableData + F.SelectorOffsets[Idx], 0); - if (DeserializationListener) - DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]); - break; - } - Idx -= F.LocalNumSelectors; - } - } - - return SelectorsLoaded[ID - 1]; -} - -Selector PCHReader::GetExternalSelector(uint32_t ID) { - return DecodeSelector(ID); -} - -uint32_t PCHReader::GetNumExternalSelectors() { - // ID 0 (the null selector) is considered an external selector. - return getTotalNumSelectors() + 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(llvm::BitstreamCursor &DeclsCursor, - 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(DeclsCursor)); - case TemplateArgument::Pack: { - unsigned NumArgs = Record[Idx++]; - llvm::SmallVector<TemplateArgument, 8> Args; - Args.reserve(NumArgs); - while (NumArgs--) - Args.push_back(ReadTemplateArgument(DeclsCursor, 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, - llvm::BitstreamCursor &DeclsCursor, - const RecordData &Record, unsigned &Idx) { - unsigned NumTemplateArgs = Record[Idx++]; - TemplArgs.reserve(NumTemplateArgs); - while (NumTemplateArgs--) - TemplArgs.push_back(ReadTemplateArgument(DeclsCursor, 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(llvm::BitstreamCursor &DeclsCursor, - 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++]); - TypeSourceInfo *TInfo = GetTypeSourceInfo(DeclsCursor, Record, Idx); - SourceRange Range = ReadSourceRange(Record, Idx); - return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, TInfo); -} - -std::pair<CXXBaseOrMemberInitializer **, unsigned> -PCHReader::ReadCXXBaseOrMemberInitializers(llvm::BitstreamCursor &Cursor, - const RecordData &Record, - unsigned &Idx) { - CXXBaseOrMemberInitializer **BaseOrMemberInitializers = 0; - unsigned NumInitializers = Record[Idx++]; - if (NumInitializers) { - ASTContext &C = *getContext(); - - BaseOrMemberInitializers - = new (C) CXXBaseOrMemberInitializer*[NumInitializers]; - for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *BaseClassInfo = 0; - bool IsBaseVirtual = false; - FieldDecl *Member = 0; - - bool IsBaseInitializer = Record[Idx++]; - if (IsBaseInitializer) { - BaseClassInfo = GetTypeSourceInfo(Cursor, Record, Idx); - IsBaseVirtual = Record[Idx++]; - } else { - Member = cast<FieldDecl>(GetDecl(Record[Idx++])); - } - SourceLocation MemberLoc = ReadSourceLocation(Record, Idx); - Expr *Init = ReadExpr(Cursor); - FieldDecl *AnonUnionMember - = cast_or_null<FieldDecl>(GetDecl(Record[Idx++])); - SourceLocation LParenLoc = ReadSourceLocation(Record, Idx); - SourceLocation RParenLoc = ReadSourceLocation(Record, Idx); - bool IsWritten = Record[Idx++]; - unsigned SourceOrderOrNumArrayIndices; - llvm::SmallVector<VarDecl *, 8> Indices; - if (IsWritten) { - SourceOrderOrNumArrayIndices = Record[Idx++]; - } else { - SourceOrderOrNumArrayIndices = Record[Idx++]; - Indices.reserve(SourceOrderOrNumArrayIndices); - for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) - Indices.push_back(cast<VarDecl>(GetDecl(Record[Idx++]))); - } - - CXXBaseOrMemberInitializer *BOMInit; - if (IsBaseInitializer) { - BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo, - IsBaseVirtual, LParenLoc, - Init, RParenLoc); - } else if (IsWritten) { - BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc, - LParenLoc, Init, RParenLoc); - } else { - BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc, - LParenLoc, Init, RParenLoc, - Indices.data(), - Indices.size()); - } - - BOMInit->setAnonUnionMember(AnonUnionMember); - BaseOrMemberInitializers[i] = BOMInit; - } - } - - return std::make_pair(BaseOrMemberInitializers, NumInitializers); -} - -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)); - } -} - -void PCHReader::FinishedDeserializing() { - assert(NumCurrentElementsDeserializing && - "FinishedDeserializing not paired with StartedDeserializing"); - if (NumCurrentElementsDeserializing == 1) { - // If any identifiers with corresponding top-level declarations have - // been loaded, load those declarations now. - while (!PendingIdentifierInfos.empty()) { - SetGloballyVisibleDecls(PendingIdentifierInfos.front().II, - PendingIdentifierInfos.front().DeclIDs, true); - PendingIdentifierInfos.pop_front(); - } - - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - if (Consumer) - PassInterestingDeclsToConsumer(); - } - --NumCurrentElementsDeserializing; -} diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp deleted file mode 100644 index aa5ce7aad6a..00000000000 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ /dev/null @@ -1,1600 +0,0 @@ -//===--- PCHReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the PCHReader::ReadDeclRecord method, which is the -// entrypoint for loading a decl. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHReader.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -using namespace clang; - - -//===----------------------------------------------------------------------===// -// Declaration deserialization -//===----------------------------------------------------------------------===// - -namespace clang { - class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> { - PCHReader &Reader; - llvm::BitstreamCursor &Cursor; - const pch::DeclID ThisDeclID; - const PCHReader::RecordData &Record; - unsigned &Idx; - pch::TypeID TypeIDForTypeDecl; - - uint64_t GetCurrentCursorOffset(); - - public: - PCHDeclReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor, - pch::DeclID thisDeclID, const PCHReader::RecordData &Record, - unsigned &Idx) - : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record), - Idx(Idx), TypeIDForTypeDecl(0) { } - - void Visit(Decl *D); - - void VisitDecl(Decl *D); - void VisitTranslationUnitDecl(TranslationUnitDecl *TU); - void VisitNamedDecl(NamedDecl *ND); - void VisitNamespaceDecl(NamespaceDecl *D); - void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - void VisitTypeDecl(TypeDecl *TD); - void VisitTypedefDecl(TypedefDecl *TD); - void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - void VisitTagDecl(TagDecl *TD); - void VisitEnumDecl(EnumDecl *ED); - void VisitRecordDecl(RecordDecl *RD); - void VisitCXXRecordDecl(CXXRecordDecl *D); - void VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D); - void VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - void VisitValueDecl(ValueDecl *VD); - void VisitEnumConstantDecl(EnumConstantDecl *ECD); - void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - void VisitDeclaratorDecl(DeclaratorDecl *DD); - void VisitFunctionDecl(FunctionDecl *FD); - void VisitCXXMethodDecl(CXXMethodDecl *D); - void VisitCXXConstructorDecl(CXXConstructorDecl *D); - void VisitCXXDestructorDecl(CXXDestructorDecl *D); - void VisitCXXConversionDecl(CXXConversionDecl *D); - void VisitFieldDecl(FieldDecl *FD); - void VisitVarDecl(VarDecl *VD); - void VisitImplicitParamDecl(ImplicitParamDecl *PD); - void VisitParmVarDecl(ParmVarDecl *PD); - void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - void VisitTemplateDecl(TemplateDecl *D); - void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); - void VisitClassTemplateDecl(ClassTemplateDecl *D); - void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); - void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - void VisitUsingDecl(UsingDecl *D); - void VisitUsingShadowDecl(UsingShadowDecl *D); - void VisitLinkageSpecDecl(LinkageSpecDecl *D); - void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); - void VisitAccessSpecDecl(AccessSpecDecl *D); - void VisitFriendDecl(FriendDecl *D); - void VisitFriendTemplateDecl(FriendTemplateDecl *D); - void VisitStaticAssertDecl(StaticAssertDecl *D); - void VisitBlockDecl(BlockDecl *BD); - - std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC); - template <typename T> void VisitRedeclarable(Redeclarable<T> *D); - - // FIXME: Reorder according to DeclNodes.td? - void VisitObjCMethodDecl(ObjCMethodDecl *D); - void VisitObjCContainerDecl(ObjCContainerDecl *D); - void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - void VisitObjCIvarDecl(ObjCIvarDecl *D); - void VisitObjCProtocolDecl(ObjCProtocolDecl *D); - void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCClassDecl(ObjCClassDecl *D); - void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); - void VisitObjCCategoryDecl(ObjCCategoryDecl *D); - void VisitObjCImplDecl(ObjCImplDecl *D); - void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); - void VisitObjCImplementationDecl(ObjCImplementationDecl *D); - void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); - void VisitObjCPropertyDecl(ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - }; -} - -uint64_t PCHDeclReader::GetCurrentCursorOffset() { - uint64_t Off = 0; - for (unsigned I = 0, N = Reader.Chain.size(); I != N; ++I) { - PCHReader::PerFileData &F = *Reader.Chain[N - I - 1]; - if (&Cursor == &F.DeclsCursor) { - Off += F.DeclsCursor.GetCurrentBitNo(); - break; - } - Off += F.SizeInBits; - } - return Off; -} - -void PCHDeclReader::Visit(Decl *D) { - DeclVisitor<PCHDeclReader, void>::Visit(D); - - if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { - // if we have a fully initialized TypeDecl, we can safely read its type now. - TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr()); - } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - // FunctionDecl's body was written last after all other Stmts/Exprs. - if (Record[Idx++]) - FD->setLazyBody(GetCurrentCursorOffset()); - } -} - -void PCHDeclReader::VisitDecl(Decl *D) { - D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); - D->setLexicalDeclContext( - cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); - D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - D->setInvalidDecl(Record[Idx++]); - if (Record[Idx++]) - D->initAttrs(Reader.ReadAttributes(Cursor)); - D->setImplicit(Record[Idx++]); - D->setUsed(Record[Idx++]); - D->setAccess((AccessSpecifier)Record[Idx++]); - D->setPCHLevel(Record[Idx++] + 1); -} - -void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { - VisitDecl(TU); - TU->setAnonymousNamespace( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) { - VisitDecl(ND); - ND->setDeclName(Reader.ReadDeclarationName(Record, Idx)); -} - -void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) { - VisitNamedDecl(TD); - // Delay type reading until after we have fully initialized the decl. - TypeIDForTypeDecl = Record[Idx++]; -} - -void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) { - VisitTypeDecl(TD); - TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx)); -} - -void PCHDeclReader::VisitTagDecl(TagDecl *TD) { - VisitTypeDecl(TD); - TD->IdentifierNamespace = Record[Idx++]; - VisitRedeclarable(TD); - TD->setTagKind((TagDecl::TagKind)Record[Idx++]); - TD->setDefinition(Record[Idx++]); - TD->setEmbeddedInDeclarator(Record[Idx++]); - TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - // FIXME: maybe read optional qualifier and its range. - TD->setTypedefForAnonDecl( - cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) { - VisitTagDecl(ED); - ED->setIntegerType(Reader.GetType(Record[Idx++])); - ED->setPromotionType(Reader.GetType(Record[Idx++])); - ED->setNumPositiveBits(Record[Idx++]); - ED->setNumNegativeBits(Record[Idx++]); - ED->setInstantiationOfMemberEnum( - cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) { - VisitTagDecl(RD); - RD->setHasFlexibleArrayMember(Record[Idx++]); - RD->setAnonymousStructOrUnion(Record[Idx++]); - RD->setHasObjectMember(Record[Idx++]); -} - -void PCHDeclReader::VisitValueDecl(ValueDecl *VD) { - VisitNamedDecl(VD); - VD->setType(Reader.GetType(Record[Idx++])); -} - -void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { - VisitValueDecl(ECD); - if (Record[Idx++]) - ECD->setInitExpr(Reader.ReadExpr(Cursor)); - ECD->setInitVal(Reader.ReadAPSInt(Record, Idx)); -} - -void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { - VisitValueDecl(DD); - TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx); - if (TInfo) - DD->setTypeSourceInfo(TInfo); - // FIXME: read optional qualifier and its range. -} - -void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { - VisitDeclaratorDecl(FD); - // FIXME: read DeclarationNameLoc. - - FD->IdentifierNamespace = Record[Idx++]; - switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { - default: assert(false && "Unhandled TemplatedKind!"); - break; - case FunctionDecl::TK_NonTemplate: - break; - case FunctionDecl::TK_FunctionTemplate: - FD->setDescribedFunctionTemplate( - cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))); - break; - case FunctionDecl::TK_MemberSpecialization: { - FunctionDecl *InstFD = cast<FunctionDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - FD->setInstantiationOfMemberFunction(InstFD, TSK); - FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - break; - } - case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateDecl *Template - = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - - // Template arguments. - llvm::SmallVector<TemplateArgument, 8> TemplArgs; - Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx); - - // Template args as written. - llvm::SmallVector<TemplateArgumentLoc, 8> TemplArgLocs; - SourceLocation LAngleLoc, RAngleLoc; - if (Record[Idx++]) { // TemplateArgumentsAsWritten != 0 - unsigned NumTemplateArgLocs = Record[Idx++]; - TemplArgLocs.reserve(NumTemplateArgLocs); - for (unsigned i=0; i != NumTemplateArgLocs; ++i) - TemplArgLocs.push_back( - Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx)); - - LAngleLoc = Reader.ReadSourceLocation(Record, Idx); - RAngleLoc = Reader.ReadSourceLocation(Record, Idx); - } - - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - - if (FD->isCanonicalDecl()) // if canonical add to template's set. - FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(), - TemplArgs.data(), TSK, - TemplArgLocs.size(), - TemplArgLocs.data(), - LAngleLoc, RAngleLoc, POI); - break; - } - case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { - // Templates. - UnresolvedSet<8> TemplDecls; - unsigned NumTemplates = Record[Idx++]; - while (NumTemplates--) - TemplDecls.addDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - - // Templates args. - TemplateArgumentListInfo TemplArgs; - unsigned NumArgs = Record[Idx++]; - while (NumArgs--) - TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(Cursor,Record, Idx)); - TemplArgs.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - TemplArgs.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - - FD->setDependentTemplateSpecialization(*Reader.getContext(), - TemplDecls, TemplArgs); - break; - } - } - - // FunctionDecl's body is handled last at PCHReaderDecl::Visit, - // after everything else is read. - - VisitRedeclarable(FD); - FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); - FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]); - FD->setInlineSpecified(Record[Idx++]); - FD->setVirtualAsWritten(Record[Idx++]); - FD->setPure(Record[Idx++]); - FD->setHasInheritedPrototype(Record[Idx++]); - FD->setHasWrittenPrototype(Record[Idx++]); - FD->setDeleted(Record[Idx++]); - FD->setTrivial(Record[Idx++]); - FD->setCopyAssignment(Record[Idx++]); - FD->setHasImplicitReturnZero(Record[Idx++]); - FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); - - // Read in the parameters. - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - FD->setParams(Params.data(), NumParams); -} - -void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { - VisitNamedDecl(MD); - if (Record[Idx++]) { - // In practice, this won't be executed (since method definitions - // don't occur in header files). - MD->setBody(Reader.ReadStmt(Cursor)); - MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); - MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); - } - MD->setInstanceMethod(Record[Idx++]); - MD->setVariadic(Record[Idx++]); - MD->setSynthesized(Record[Idx++]); - MD->setDefined(Record[Idx++]); - MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); - MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); - MD->setNumSelectorArgs(unsigned(Record[Idx++])); - MD->setResultType(Reader.GetType(Record[Idx++])); - MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx)); - MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams, - NumParams); -} - -void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { - VisitNamedDecl(CD); - SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]); - CD->setAtEndRange(SourceRange(A, B)); -} - -void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { - VisitObjCContainerDecl(ID); - ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr()); - ID->setSuperClass(cast_or_null<ObjCInterfaceDecl> - (Reader.GetDecl(Record[Idx++]))); - unsigned NumProtocols = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols; - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), - *Reader.getContext()); - unsigned NumIvars = Record[Idx++]; - llvm::SmallVector<ObjCIvarDecl *, 16> IVars; - IVars.reserve(NumIvars); - for (unsigned I = 0; I != NumIvars; ++I) - IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); - ID->setCategoryList( - cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); - ID->setForwardDecl(Record[Idx++]); - ID->setImplicitInterfaceDecl(Record[Idx++]); - ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { - VisitFieldDecl(IVD); - IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]); - bool synth = Record[Idx++]; - IVD->setSynthesize(synth); -} - -void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { - VisitObjCContainerDecl(PD); - PD->setForwardDecl(Record[Idx++]); - PD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); - unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); -} - -void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { - VisitFieldDecl(FD); -} - -void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) { - VisitDecl(CD); - unsigned NumClassRefs = Record[Idx++]; - llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs; - ClassRefs.reserve(NumClassRefs); - for (unsigned I = 0; I != NumClassRefs; ++I) - ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> SLocs; - SLocs.reserve(NumClassRefs); - for (unsigned I = 0; I != NumClassRefs; ++I) - SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(), - NumClassRefs); -} - -void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) { - VisitDecl(FPD); - unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); -} - -void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { - VisitObjCContainerDecl(CD); - CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - unsigned NumProtoRefs = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); - CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - *Reader.getContext()); - CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); - CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { - VisitNamedDecl(CAD); - CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { - VisitNamedDecl(D); - D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - D->setType(Reader.GetTypeSourceInfo(Cursor, Record, Idx)); - // FIXME: stable encoding - D->setPropertyAttributes( - (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]); - D->setPropertyAttributesAsWritten( - (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]); - // FIXME: stable encoding - D->setPropertyImplementation( - (ObjCPropertyDecl::PropertyControl)Record[Idx++]); - D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); - D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); - D->setGetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - D->setSetterMethodDecl( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - D->setPropertyIvarDecl( - cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitObjCContainerDecl(D); - D->setClassInterface( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - VisitObjCImplDecl(D); - D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx)); -} - -void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { - VisitObjCImplDecl(D); - D->setSuperClass( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - llvm::tie(D->IvarInitializers, D->NumIvarInitializers) - = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx); -} - - -void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - VisitDecl(D); - D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - D->setPropertyDecl( - cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++]))); - D->setPropertyIvarDecl( - cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); - D->setGetterCXXConstructor(Reader.ReadExpr(Cursor)); - D->setSetterCXXAssignment(Reader.ReadExpr(Cursor)); -} - -void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) { - VisitDeclaratorDecl(FD); - FD->setMutable(Record[Idx++]); - if (Record[Idx++]) - FD->setBitWidth(Reader.ReadExpr(Cursor)); - if (!FD->getDeclName()) { - FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])); - if (Tmpl) - Reader.getContext()->setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); - } -} - -void PCHDeclReader::VisitVarDecl(VarDecl *VD) { - VisitDeclaratorDecl(VD); - VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]); - VD->setStorageClassAsWritten((VarDecl::StorageClass)Record[Idx++]); - VD->setThreadSpecified(Record[Idx++]); - VD->setCXXDirectInitializer(Record[Idx++]); - VD->setExceptionVariable(Record[Idx++]); - VD->setNRVOVariable(Record[Idx++]); - VisitRedeclarable(VD); - if (Record[Idx++]) - VD->setInit(Reader.ReadExpr(Cursor)); - - if (Record[Idx++]) { // HasMemberSpecializationInfo. - VarDecl *Tmpl = cast<VarDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - Reader.getContext()->setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); - } -} - -void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { - VisitVarDecl(PD); -} - -void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { - VisitVarDecl(PD); - PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); - PD->setHasInheritedDefaultArg(Record[Idx++]); - if (Record[Idx++]) // hasUninstantiatedDefaultArg. - PD->setUninstantiatedDefaultArg(Reader.ReadExpr(Cursor)); -} - -void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { - VisitDecl(AD); - AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(Cursor))); -} - -void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) { - VisitDecl(BD); - BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(Cursor))); - BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Cursor, Record, Idx)); - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<ParmVarDecl *, 16> Params; - Params.reserve(NumParams); - for (unsigned I = 0; I != NumParams; ++I) - Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - BD->setParams(Params.data(), NumParams); -} - -void PCHDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { - VisitDecl(D); - D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]); - D->setHasBraces(Record[Idx++]); -} - -void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { - VisitNamedDecl(D); - D->setLBracLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setRBracLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setNextNamespace( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); - - bool IsOriginal = Record[Idx++]; - D->OrigOrAnonNamespace.setInt(IsOriginal); - D->OrigOrAnonNamespace.setPointer( - cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - VisitNamedDecl(D); - - D->setAliasLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - D->setTargetNameLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setAliasedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitUsingDecl(UsingDecl *D) { - VisitNamedDecl(D); - D->setUsingLocation(Reader.ReadSourceLocation(Record, Idx)); - D->setNestedNameRange(Reader.ReadSourceRange(Record, Idx)); - D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx)); - // FIXME: read the DNLoc component. - - // FIXME: It would probably be more efficient to read these into a vector - // and then re-cosntruct the shadow decl set over that vector since it - // would avoid existence checks. - unsigned NumShadows = Record[Idx++]; - for(unsigned I = 0; I != NumShadows; ++I) { - // Avoid invariant checking of UsingDecl::addShadowDecl, the decl may still - // be initializing. - D->Shadows.insert(cast<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]))); - } - D->setTypeName(Record[Idx++]); - NamedDecl *Pattern = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); - if (Pattern) - Reader.getContext()->setInstantiatedFromUsingDecl(D, Pattern); -} - -void PCHDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { - VisitNamedDecl(D); - D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - D->setUsingDecl(cast<UsingDecl>(Reader.GetDecl(Record[Idx++]))); - UsingShadowDecl *Pattern - = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])); - if (Pattern) - Reader.getContext()->setInstantiatedFromUsingShadowDecl(D, Pattern); -} - -void PCHDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - VisitNamedDecl(D); - D->setNamespaceKeyLocation(Reader.ReadSourceLocation(Record, Idx)); - D->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - D->setIdentLocation(Reader.ReadSourceLocation(Record, Idx)); - D->setNominatedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - D->setCommonAncestor(cast_or_null<DeclContext>( - Reader.GetDecl(Record[Idx++]))); -} - -void PCHDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - VisitValueDecl(D); - D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx)); - D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - // FIXME: read the DNLoc component. -} - -void PCHDeclReader::VisitUnresolvedUsingTypenameDecl( - UnresolvedUsingTypenameDecl *D) { - VisitTypeDecl(D); - D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx)); - D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTypenameLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); -} - -void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { - ASTContext &C = *Reader.getContext(); - - // We need to allocate the DefinitionData struct ahead of VisitRecordDecl - // so that the other CXXRecordDecls can get a pointer even when the owner - // is still initializing. - bool OwnsDefinitionData = false; - enum DataOwnership { Data_NoDefData, Data_Owner, Data_NotOwner }; - switch ((DataOwnership)Record[Idx++]) { - default: - assert(0 && "Out of sync with PCHDeclWriter or messed up reading"); - case Data_NoDefData: - break; - case Data_Owner: - OwnsDefinitionData = true; - D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); - break; - case Data_NotOwner: - D->DefinitionData - = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]))->DefinitionData; - break; - } - - VisitRecordDecl(D); - - if (OwnsDefinitionData) { - assert(D->DefinitionData); - struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; - - Data.UserDeclaredConstructor = Record[Idx++]; - Data.UserDeclaredCopyConstructor = Record[Idx++]; - Data.UserDeclaredCopyAssignment = Record[Idx++]; - Data.UserDeclaredDestructor = Record[Idx++]; - Data.Aggregate = Record[Idx++]; - Data.PlainOldData = Record[Idx++]; - Data.Empty = Record[Idx++]; - Data.Polymorphic = Record[Idx++]; - Data.Abstract = Record[Idx++]; - Data.HasTrivialConstructor = Record[Idx++]; - Data.HasTrivialCopyConstructor = Record[Idx++]; - Data.HasTrivialCopyAssignment = Record[Idx++]; - Data.HasTrivialDestructor = Record[Idx++]; - Data.ComputedVisibleConversions = Record[Idx++]; - Data.DeclaredDefaultConstructor = Record[Idx++]; - Data.DeclaredCopyConstructor = Record[Idx++]; - Data.DeclaredCopyAssignment = Record[Idx++]; - Data.DeclaredDestructor = Record[Idx++]; - - // setBases() is unsuitable since it may try to iterate the bases of an - // uninitialized base. - Data.NumBases = Record[Idx++]; - Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases]; - for (unsigned i = 0; i != Data.NumBases; ++i) - Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx); - - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Data.NumVBases = Record[Idx++]; - Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases]; - for (unsigned i = 0; i != Data.NumVBases; ++i) - Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx); - - Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx); - Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx); - assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend - = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++])); - } - - enum CXXRecKind { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization - }; - switch ((CXXRecKind)Record[Idx++]) { - default: - assert(false && "Out of sync with PCHDeclWriter::VisitCXXRecordDecl?"); - case CXXRecNotTemplate: - break; - case CXXRecTemplate: - D->setDescribedClassTemplate( - cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]))); - break; - case CXXRecMemberSpecialization: { - CXXRecordDecl *RD = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])); - TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - D->setInstantiationOfMemberClass(RD, TSK); - D->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - break; - } - } -} - -void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { - VisitFunctionDecl(D); - unsigned NumOverridenMethods = Record[Idx++]; - while (NumOverridenMethods--) { - CXXMethodDecl *MD = cast<CXXMethodDecl>(Reader.GetDecl(Record[Idx++])); - // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod, - // MD may be initializing. - Reader.getContext()->addOverriddenMethod(D, MD); - } -} - -void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - VisitCXXMethodDecl(D); - - D->IsExplicitSpecified = Record[Idx++]; - D->ImplicitlyDefined = Record[Idx++]; - llvm::tie(D->BaseOrMemberInitializers, D->NumBaseOrMemberInitializers) - = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx); -} - -void PCHDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - VisitCXXMethodDecl(D); - - D->ImplicitlyDefined = Record[Idx++]; - D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])); -} - -void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { - VisitCXXMethodDecl(D); - D->IsExplicitSpecified = Record[Idx++]; -} - -void PCHDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { - VisitDecl(D); - D->setColonLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHDeclReader::VisitFriendDecl(FriendDecl *D) { - VisitDecl(D); - if (Record[Idx++]) - D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx); - else - D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); - D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++])); - D->FriendLoc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { - VisitDecl(D); - unsigned NumParams = Record[Idx++]; - D->NumParams = NumParams; - D->Params = new TemplateParameterList*[NumParams]; - for (unsigned i = 0; i != NumParams; ++i) - D->Params[i] = Reader.ReadTemplateParameterList(Record, Idx); - if (Record[Idx++]) // HasFriendDecl - D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); - else - D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx); - D->FriendLoc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) { - VisitNamedDecl(D); - - NamedDecl *TemplatedDecl - = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])); - TemplateParameterList* TemplateParams - = Reader.ReadTemplateParameterList(Record, Idx); - D->init(TemplatedDecl, TemplateParams); -} - -void PCHDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { - VisitTemplateDecl(D); - - D->IdentifierNamespace = Record[Idx++]; - RedeclarableTemplateDecl *PrevDecl = - cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++])); - assert((PrevDecl == 0 || PrevDecl->getKind() == D->getKind()) && - "PrevDecl kind mismatch"); - if (PrevDecl) - D->CommonOrPrev = PrevDecl; - if (PrevDecl == 0) { - if (RedeclarableTemplateDecl *RTD - = cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]))) { - assert(RTD->getKind() == D->getKind() && - "InstantiatedFromMemberTemplate kind mismatch"); - D->setInstantiatedFromMemberTemplateImpl(RTD); - if (Record[Idx++]) - D->setMemberSpecialization(); - } - - RedeclarableTemplateDecl *LatestDecl = - cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++])); - - // This decl is a first one and the latest declaration that it points to is - // in the same PCH. However, if this actually needs to point to a - // redeclaration in another chained PCH, we need to update it by checking - // the FirstLatestDeclIDs map which tracks this kind of decls. - assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?"); - PCHReader::FirstLatestDeclIDMap::iterator I - = Reader.FirstLatestDeclIDs.find(ThisDeclID); - if (I != Reader.FirstLatestDeclIDs.end()) { - Decl *NewLatest = Reader.GetDecl(I->second); - assert((LatestDecl->getLocation().isInvalid() || - NewLatest->getLocation().isInvalid() || - Reader.SourceMgr.isBeforeInTranslationUnit( - LatestDecl->getLocation(), - NewLatest->getLocation())) && - "The new latest is supposed to come after the previous latest"); - LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest); - } - - assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch"); - D->getCommonPtr()->Latest = LatestDecl; - } -} - -void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - - if (D->getPreviousDeclaration() == 0) { - // This ClassTemplateDecl owns a CommonPtr; read it. - - // FoldingSets are filled in VisitClassTemplateSpecializationDecl. - unsigned size = Record[Idx++]; - while (size--) - cast<ClassTemplateSpecializationDecl>(Reader.GetDecl(Record[Idx++])); - - size = Record[Idx++]; - while (size--) - cast<ClassTemplatePartialSpecializationDecl>( - Reader.GetDecl(Record[Idx++])); - - // InjectedClassNameType is computed. - } -} - -void PCHDeclReader::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - VisitCXXRecordDecl(D); - - if (Decl *InstD = Reader.GetDecl(Record[Idx++])) { - if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) { - D->setInstantiationOf(CTD); - } else { - llvm::SmallVector<TemplateArgument, 8> TemplArgs; - Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx); - D->setInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(InstD), - TemplArgs.data(), TemplArgs.size()); - } - } - - // Explicit info. - if (TypeSourceInfo *TyInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx)) { - D->setTypeAsWritten(TyInfo); - D->setExternLoc(Reader.ReadSourceLocation(Record, Idx)); - D->setTemplateKeywordLoc(Reader.ReadSourceLocation(Record, Idx)); - } - - llvm::SmallVector<TemplateArgument, 8> TemplArgs; - Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx); - D->initTemplateArgs(TemplArgs.data(), TemplArgs.size()); - SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - if (POI.isValid()) - D->setPointOfInstantiation(POI); - D->setSpecializationKind((TemplateSpecializationKind)Record[Idx++]); - - if (D->isCanonicalDecl()) { // It's kept in the folding set. - ClassTemplateDecl *CanonPattern - = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])); - if (ClassTemplatePartialSpecializationDecl *Partial - = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { - CanonPattern->getPartialSpecializations().InsertNode(Partial); - } else { - CanonPattern->getSpecializations().InsertNode(D); - } - } -} - -void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); - - D->initTemplateParameters(Reader.ReadTemplateParameterList(Record, Idx)); - - TemplateArgumentListInfo ArgInfos; - unsigned NumArgs = Record[Idx++]; - while (NumArgs--) - ArgInfos.addArgument(Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx)); - D->initTemplateArgsAsWritten(ArgInfos); - - D->setSequenceNumber(Record[Idx++]); - - // These are read/set from/to the first declaration. - if (D->getPreviousDeclaration() == 0) { - D->setInstantiatedFromMember( - cast_or_null<ClassTemplatePartialSpecializationDecl>( - Reader.GetDecl(Record[Idx++]))); - if (Record[Idx++]) - D->setMemberSpecialization(); - } -} - -void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - - if (D->getPreviousDeclaration() == 0) { - // This FunctionTemplateDecl owns a CommonPtr; read it. - - // Read the function specialization declarations. - // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled - // through the specialized FunctionDecl's setFunctionTemplateSpecialization. - unsigned NumSpecs = Record[Idx++]; - while (NumSpecs--) - Reader.GetDecl(Record[Idx++]); - } -} - -void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { - VisitTypeDecl(D); - - D->setDeclaredWithTypename(Record[Idx++]); - D->setParameterPack(Record[Idx++]); - - bool Inherited = Record[Idx++]; - TypeSourceInfo *DefArg = Reader.GetTypeSourceInfo(Cursor, Record, Idx); - D->setDefaultArgument(DefArg, Inherited); -} - -void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { - VisitVarDecl(D); - // TemplateParmPosition. - D->setDepth(Record[Idx++]); - D->setPosition(Record[Idx++]); - // Rest of NonTypeTemplateParmDecl. - if (Record[Idx++]) { - Expr *DefArg = Reader.ReadExpr(Cursor); - bool Inherited = Record[Idx++]; - D->setDefaultArgument(DefArg, Inherited); - } -} - -void PCHDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { - VisitTemplateDecl(D); - // TemplateParmPosition. - D->setDepth(Record[Idx++]); - D->setPosition(Record[Idx++]); - // Rest of TemplateTemplateParmDecl. - TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx); - bool IsInherited = Record[Idx++]; - D->setDefaultArgument(Arg, IsInherited); -} - -void PCHDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { - VisitDecl(D); - D->AssertExpr = Reader.ReadExpr(Cursor); - D->Message = cast<StringLiteral>(Reader.ReadExpr(Cursor)); -} - -std::pair<uint64_t, uint64_t> -PCHDeclReader::VisitDeclContext(DeclContext *DC) { - uint64_t LexicalOffset = Record[Idx++]; - uint64_t VisibleOffset = Record[Idx++]; - return std::make_pair(LexicalOffset, VisibleOffset); -} - -template <typename T> -void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) { - enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest }; - RedeclKind Kind = (RedeclKind)Record[Idx++]; - switch (Kind) { - default: - assert(0 && "Out of sync with PCHDeclWriter::VisitRedeclarable or messed up" - " reading"); - case NoRedeclaration: - break; - case PointsToPrevious: - D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink( - cast_or_null<T>(Reader.GetDecl(Record[Idx++]))); - break; - case PointsToLatest: - D->RedeclLink = typename Redeclarable<T>::LatestDeclLink( - cast_or_null<T>(Reader.GetDecl(Record[Idx++]))); - break; - } - - assert(!(Kind == PointsToPrevious && - Reader.FirstLatestDeclIDs.find(ThisDeclID) != - Reader.FirstLatestDeclIDs.end()) && - "This decl is not first, it should not be in the map"); - if (Kind == PointsToPrevious) - return; - - // This decl is a first one and the latest declaration that it points to is in - // the same PCH. However, if this actually needs to point to a redeclaration - // in another chained PCH, we need to update it by checking the - // FirstLatestDeclIDs map which tracks this kind of decls. - assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) && - "Invalid ThisDeclID ?"); - PCHReader::FirstLatestDeclIDMap::iterator I - = Reader.FirstLatestDeclIDs.find(ThisDeclID); - if (I != Reader.FirstLatestDeclIDs.end()) { - Decl *NewLatest = Reader.GetDecl(I->second); - assert((D->getMostRecentDeclaration()->getLocation().isInvalid() || - NewLatest->getLocation().isInvalid() || - Reader.SourceMgr.isBeforeInTranslationUnit( - D->getMostRecentDeclaration()->getLocation(), - NewLatest->getLocation())) && - "The new latest is supposed to come after the previous latest"); - D->RedeclLink - = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest)); - } -} - -//===----------------------------------------------------------------------===// -// Attribute Reading -//===----------------------------------------------------------------------===// - -/// \brief Reads attributes from the current stream position. -Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) { - unsigned Code = DeclsCursor.ReadCode(); - assert(Code == llvm::bitc::UNABBREV_RECORD && - "Expected unabbreviated record"); (void)Code; - - RecordData Record; - unsigned Idx = 0; - unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - assert(RecCode == pch::DECL_ATTR && "Expected attribute record"); - (void)RecCode; - -#define SIMPLE_ATTR(Name) \ - case attr::Name: \ - New = ::new (*Context) Name##Attr(); \ - break - -#define STRING_ATTR(Name) \ - case attr::Name: \ - New = ::new (*Context) Name##Attr(*Context, ReadString(Record, Idx)); \ - break - -#define UNSIGNED_ATTR(Name) \ - case attr::Name: \ - New = ::new (*Context) Name##Attr(Record[Idx++]); \ - break - - Attr *Attrs = 0; - while (Idx < Record.size()) { - Attr *New = 0; - attr::Kind Kind = (attr::Kind)Record[Idx++]; - bool IsInherited = Record[Idx++]; - - switch (Kind) { - default: - assert(0 && "Unknown attribute!"); - break; - STRING_ATTR(Alias); - SIMPLE_ATTR(AlignMac68k); - UNSIGNED_ATTR(Aligned); - SIMPLE_ATTR(AlwaysInline); - SIMPLE_ATTR(AnalyzerNoReturn); - STRING_ATTR(Annotate); - STRING_ATTR(AsmLabel); - SIMPLE_ATTR(BaseCheck); - - case attr::Blocks: - New = ::new (*Context) BlocksAttr( - (BlocksAttr::BlocksAttrTypes)Record[Idx++]); - break; - - SIMPLE_ATTR(CDecl); - - case attr::Cleanup: - New = ::new (*Context) CleanupAttr( - cast<FunctionDecl>(GetDecl(Record[Idx++]))); - break; - - SIMPLE_ATTR(Const); - UNSIGNED_ATTR(Constructor); - SIMPLE_ATTR(DLLExport); - SIMPLE_ATTR(DLLImport); - SIMPLE_ATTR(Deprecated); - UNSIGNED_ATTR(Destructor); - SIMPLE_ATTR(FastCall); - SIMPLE_ATTR(Final); - - case attr::Format: { - std::string Type = ReadString(Record, Idx); - unsigned FormatIdx = Record[Idx++]; - unsigned FirstArg = Record[Idx++]; - New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg); - break; - } - - case attr::FormatArg: { - unsigned FormatIdx = Record[Idx++]; - New = ::new (*Context) FormatArgAttr(FormatIdx); - break; - } - - case attr::Sentinel: { - int sentinel = Record[Idx++]; - int nullPos = Record[Idx++]; - New = ::new (*Context) SentinelAttr(sentinel, nullPos); - break; - } - - SIMPLE_ATTR(GNUInline); - SIMPLE_ATTR(Hiding); - - case attr::IBAction: - New = ::new (*Context) IBActionAttr(); - break; - - case attr::IBOutlet: - New = ::new (*Context) IBOutletAttr(); - break; - - case attr::IBOutletCollection: { - ObjCInterfaceDecl *D = - cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); - New = ::new (*Context) IBOutletCollectionAttr(D); - break; - } - - SIMPLE_ATTR(Malloc); - SIMPLE_ATTR(NoDebug); - SIMPLE_ATTR(NoInline); - SIMPLE_ATTR(NoReturn); - SIMPLE_ATTR(NoThrow); - - case attr::NonNull: { - unsigned Size = Record[Idx++]; - llvm::SmallVector<unsigned, 16> ArgNums; - ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size); - Idx += Size; - New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size); - break; - } - - case attr::ReqdWorkGroupSize: { - unsigned X = Record[Idx++]; - unsigned Y = Record[Idx++]; - unsigned Z = Record[Idx++]; - New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z); - break; - } - - SIMPLE_ATTR(ObjCException); - SIMPLE_ATTR(ObjCNSObject); - SIMPLE_ATTR(CFReturnsNotRetained); - SIMPLE_ATTR(CFReturnsRetained); - SIMPLE_ATTR(NSReturnsNotRetained); - SIMPLE_ATTR(NSReturnsRetained); - SIMPLE_ATTR(Overloadable); - SIMPLE_ATTR(Override); - SIMPLE_ATTR(Packed); - UNSIGNED_ATTR(MaxFieldAlignment); - SIMPLE_ATTR(Pure); - UNSIGNED_ATTR(Regparm); - STRING_ATTR(Section); - SIMPLE_ATTR(StdCall); - SIMPLE_ATTR(ThisCall); - SIMPLE_ATTR(TransparentUnion); - SIMPLE_ATTR(Unavailable); - SIMPLE_ATTR(Unused); - SIMPLE_ATTR(Used); - - case attr::Visibility: - New = ::new (*Context) VisibilityAttr( - (VisibilityAttr::VisibilityTypes)Record[Idx++], - (bool)Record[Idx++]); - break; - - SIMPLE_ATTR(WarnUnusedResult); - SIMPLE_ATTR(Weak); - SIMPLE_ATTR(WeakRef); - SIMPLE_ATTR(WeakImport); - } - - assert(New && "Unable to decode attribute?"); - New->setInherited(IsInherited); - New->setNext(Attrs); - Attrs = New; - } -#undef UNSIGNED_ATTR -#undef STRING_ATTR -#undef SIMPLE_ATTR - - // The list of attributes was built backwards. Reverse the list - // before returning it. - Attr *PrevAttr = 0, *NextAttr = 0; - while (Attrs) { - NextAttr = Attrs->getNext(); - Attrs->setNext(PrevAttr); - PrevAttr = Attrs; - Attrs = NextAttr; - } - - return PrevAttr; -} - -//===----------------------------------------------------------------------===// -// PCHReader Implementation -//===----------------------------------------------------------------------===// - -/// \brief Note that we have loaded the declaration with the given -/// Index. -/// -/// This routine notes that this declaration has already been loaded, -/// so that future GetDecl calls will return this declaration rather -/// than trying to load a new declaration. -inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) { - assert(!DeclsLoaded[Index] && "Decl loaded twice?"); - DeclsLoaded[Index] = D; -} - - -/// \brief Determine whether the consumer will be interested in seeing -/// this declaration (via HandleTopLevelDecl). -/// -/// This routine should return true for anything that might affect -/// code generation, e.g., inline function definitions, Objective-C -/// declarations with metadata, etc. -static bool isConsumerInterestedIn(Decl *D) { - if (isa<FileScopeAsmDecl>(D)) - return true; - if (VarDecl *Var = dyn_cast<VarDecl>(D)) - return Var->isFileVarDecl() && - Var->isThisDeclarationADefinition() == VarDecl::Definition; - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) - return Func->isThisDeclarationADefinition(); - return isa<ObjCProtocolDecl>(D) || isa<ObjCImplementationDecl>(D); -} - -/// \brief Get the correct cursor and offset for loading a type. -PCHReader::RecordLocation -PCHReader::DeclCursorForIndex(unsigned Index, pch::DeclID ID) { - // See if there's an override. - DeclReplacementMap::iterator It = ReplacedDecls.find(ID); - if (It != ReplacedDecls.end()) - return RecordLocation(&It->second.first->DeclsCursor, It->second.second); - - PerFileData *F = 0; - for (unsigned I = 0, N = Chain.size(); I != N; ++I) { - F = Chain[N - I - 1]; - if (Index < F->LocalNumDecls) - break; - Index -= F->LocalNumDecls; - } - assert(F && F->LocalNumDecls > Index && "Broken chain"); - return RecordLocation(&F->DeclsCursor, F->DeclOffsets[Index]); -} - -/// \brief Read the declaration at the given offset from the PCH file. -Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) { - RecordLocation Loc = DeclCursorForIndex(Index, ID); - llvm::BitstreamCursor &DeclsCursor = *Loc.first; - // Keep track of where we are in the stream, then jump back there - // after reading this declaration. - SavedStreamPosition SavedPosition(DeclsCursor); - - ReadingKindTracker ReadingKind(Read_Decl, *this); - - // Note that we are loading a declaration record. - Deserializing ADecl(this); - - DeclsCursor.JumpToBit(Loc.second); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - unsigned Idx = 0; - PCHDeclReader Reader(*this, DeclsCursor, ID, Record, Idx); - - Decl *D = 0; - switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) { - case pch::DECL_ATTR: - case pch::DECL_CONTEXT_LEXICAL: - case pch::DECL_CONTEXT_VISIBLE: - assert(false && "Record cannot be de-serialized with ReadDeclRecord"); - break; - case pch::DECL_TRANSLATION_UNIT: - assert(Index == 0 && "Translation unit must be at index 0"); - D = Context->getTranslationUnitDecl(); - break; - case pch::DECL_TYPEDEF: - D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_ENUM: - D = EnumDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_RECORD: - D = RecordDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_ENUM_CONSTANT: - D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), - 0, llvm::APSInt()); - break; - case pch::DECL_FUNCTION: - D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(), - QualType(), 0); - break; - case pch::DECL_LINKAGE_SPEC: - D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(), - (LinkageSpecDecl::LanguageIDs)0, - false); - break; - case pch::DECL_NAMESPACE: - D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_NAMESPACE_ALIAS: - D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), 0, SourceRange(), 0, - SourceLocation(), 0); - break; - case pch::DECL_USING: - D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(), - 0, DeclarationNameInfo(), false); - break; - case pch::DECL_USING_SHADOW: - D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_USING_DIRECTIVE: - D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceRange(), 0, - SourceLocation(), 0, 0); - break; - case pch::DECL_UNRESOLVED_USING_VALUE: - D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(), - SourceRange(), 0, - DeclarationNameInfo()); - break; - case pch::DECL_UNRESOLVED_USING_TYPENAME: - D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceRange(), - 0, SourceLocation(), - DeclarationName()); - break; - case pch::DECL_CXX_RECORD: - D = CXXRecordDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CXX_METHOD: - D = CXXMethodDecl::Create(*Context, 0, DeclarationNameInfo(), - QualType(), 0); - break; - case pch::DECL_CXX_CONSTRUCTOR: - D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CXX_DESTRUCTOR: - D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CXX_CONVERSION: - D = CXXConversionDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_ACCESS_SPEC: - D = AccessSpecDecl::Create(*Context, AS_none, 0, SourceLocation(), - SourceLocation()); - break; - case pch::DECL_FRIEND: - D = FriendDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_FRIEND_TEMPLATE: - D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CLASS_TEMPLATE: - D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(), - DeclarationName(), 0, 0, 0); - break; - case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION: - D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: - D = ClassTemplatePartialSpecializationDecl::Create(*Context, - Decl::EmptyShell()); - break; - case pch::DECL_FUNCTION_TEMPLATE: - D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(), - DeclarationName(), 0, 0); - break; - case pch::DECL_TEMPLATE_TYPE_PARM: - D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell()); - break; - case pch::DECL_NON_TYPE_TEMPLATE_PARM: - D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0, - QualType(),0); - break; - case pch::DECL_TEMPLATE_TEMPLATE_PARM: - D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(),0,0,0,0); - break; - case pch::DECL_STATIC_ASSERT: - D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - - case pch::DECL_OBJC_METHOD: - D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(), - Selector(), QualType(), 0, 0); - break; - case pch::DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_OBJC_IVAR: - D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - ObjCIvarDecl::None); - break; - case pch::DECL_OBJC_PROTOCOL: - D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0, - QualType(), 0); - break; - case pch::DECL_OBJC_CLASS: - D = ObjCClassDecl::Create(*Context, 0, SourceLocation()); - break; - case pch::DECL_OBJC_FORWARD_PROTOCOL: - D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation()); - break; - case pch::DECL_OBJC_CATEGORY: - D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceLocation(), 0); - break; - case pch::DECL_OBJC_CATEGORY_IMPL: - D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_OBJC_IMPLEMENTATION: - D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_OBJC_COMPATIBLE_ALIAS: - D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0); - break; - case pch::DECL_OBJC_PROPERTY: - D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), - 0); - break; - case pch::DECL_OBJC_PROPERTY_IMPL: - D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), 0, - ObjCPropertyImplDecl::Dynamic, 0); - break; - case pch::DECL_FIELD: - D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0, - false); - break; - case pch::DECL_VAR: - D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - VarDecl::None, VarDecl::None); - break; - - case pch::DECL_IMPLICIT_PARAM: - D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType()); - break; - - case pch::DECL_PARM_VAR: - D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - VarDecl::None, VarDecl::None, 0); - break; - case pch::DECL_FILE_SCOPE_ASM: - D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0); - break; - case pch::DECL_BLOCK: - D = BlockDecl::Create(*Context, 0, SourceLocation()); - break; - } - - assert(D && "Unknown declaration reading PCH file"); - LoadedDecl(Index, D); - Reader.Visit(D); - - // If this declaration is also a declaration context, get the - // offsets for its tables of lexical and visible declarations. - if (DeclContext *DC = dyn_cast<DeclContext>(D)) { - std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); - if (Offsets.first || Offsets.second) { - DC->setHasExternalLexicalStorage(Offsets.first != 0); - DC->setHasExternalVisibleStorage(Offsets.second != 0); - DeclContextInfo Info; - if (ReadDeclContextStorage(DeclsCursor, Offsets, Info)) - return 0; - DeclContextInfos &Infos = DeclContextOffsets[DC]; - // Reading the TU will happen after reading its update blocks, so we need - // to make sure we insert in front. For all other contexts, the vector - // is empty here anyway, so there's no loss in efficiency. - Infos.insert(Infos.begin(), Info); - } - } - assert(Idx == Record.size()); - - // If we have deserialized a declaration that has a definition the - // AST consumer might need to know about, queue it. - // We don't pass it to the consumer immediately because we may be in recursive - // loading, and some declarations may still be initializing. - if (isConsumerInterestedIn(D)) - InterestingDecls.push_back(D); - - return D; -} - -bool PCHReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, - const std::pair<uint64_t, uint64_t> &Offsets, - DeclContextInfo &Info) { - SavedStreamPosition SavedPosition(Cursor); - // First the lexical decls. - if (Offsets.first != 0) { - Cursor.JumpToBit(Offsets.first); - - RecordData Record; - const char *Blob; - unsigned BlobLen; - unsigned Code = Cursor.ReadCode(); - unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen); - if (RecCode != pch::DECL_CONTEXT_LEXICAL) { - Error("Expected lexical block"); - return true; - } - - Info.LexicalDecls = reinterpret_cast<const pch::DeclID*>(Blob); - Info.NumLexicalDecls = BlobLen / sizeof(pch::DeclID); - } else { - Info.LexicalDecls = 0; - Info.NumLexicalDecls = 0; - } - - // Now the visible decls. - Info.Stream = &Cursor; - Info.OffsetToVisibleDecls = Offsets.second; - - return false; -} diff --git a/clang/lib/Frontend/PCHReaderStmt.cpp b/clang/lib/Frontend/PCHReaderStmt.cpp deleted file mode 100644 index 41c8a9aedc2..00000000000 --- a/clang/lib/Frontend/PCHReaderStmt.cpp +++ /dev/null @@ -1,1775 +0,0 @@ -//===--- PCHReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Statement/expression deserialization. This implements the -// PCHReader::ReadStmt method. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHReader.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/StmtVisitor.h" -using namespace clang; - -namespace clang { - - class PCHStmtReader : public StmtVisitor<PCHStmtReader> { - PCHReader &Reader; - llvm::BitstreamCursor &DeclsCursor; - const PCHReader::RecordData &Record; - unsigned &Idx; - - public: - PCHStmtReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor, - const PCHReader::RecordData &Record, unsigned &Idx) - : Reader(Reader), DeclsCursor(Cursor), Record(Record), Idx(Idx) { } - - /// \brief The number of record fields required for the Stmt class - /// itself. - static const unsigned NumStmtFields = 0; - - /// \brief The number of record fields required for the Expr class - /// itself. - static const unsigned NumExprFields = NumStmtFields + 3; - - /// \brief Read and initialize a ExplicitTemplateArgumentList structure. - void ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList, - unsigned NumTemplateArgs); - - void VisitStmt(Stmt *S); - void VisitNullStmt(NullStmt *S); - void VisitCompoundStmt(CompoundStmt *S); - void VisitSwitchCase(SwitchCase *S); - void VisitCaseStmt(CaseStmt *S); - void VisitDefaultStmt(DefaultStmt *S); - void VisitLabelStmt(LabelStmt *S); - void VisitIfStmt(IfStmt *S); - void VisitSwitchStmt(SwitchStmt *S); - void VisitWhileStmt(WhileStmt *S); - void VisitDoStmt(DoStmt *S); - void VisitForStmt(ForStmt *S); - void VisitGotoStmt(GotoStmt *S); - void VisitIndirectGotoStmt(IndirectGotoStmt *S); - void VisitContinueStmt(ContinueStmt *S); - void VisitBreakStmt(BreakStmt *S); - void VisitReturnStmt(ReturnStmt *S); - void VisitDeclStmt(DeclStmt *S); - void VisitAsmStmt(AsmStmt *S); - void VisitExpr(Expr *E); - void VisitPredefinedExpr(PredefinedExpr *E); - void VisitDeclRefExpr(DeclRefExpr *E); - void VisitIntegerLiteral(IntegerLiteral *E); - void VisitFloatingLiteral(FloatingLiteral *E); - void VisitImaginaryLiteral(ImaginaryLiteral *E); - void VisitStringLiteral(StringLiteral *E); - void VisitCharacterLiteral(CharacterLiteral *E); - void VisitParenExpr(ParenExpr *E); - void VisitParenListExpr(ParenListExpr *E); - void VisitUnaryOperator(UnaryOperator *E); - void VisitOffsetOfExpr(OffsetOfExpr *E); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); - void VisitArraySubscriptExpr(ArraySubscriptExpr *E); - void VisitCallExpr(CallExpr *E); - void VisitMemberExpr(MemberExpr *E); - void VisitCastExpr(CastExpr *E); - void VisitBinaryOperator(BinaryOperator *E); - void VisitCompoundAssignOperator(CompoundAssignOperator *E); - void VisitConditionalOperator(ConditionalOperator *E); - void VisitImplicitCastExpr(ImplicitCastExpr *E); - void VisitExplicitCastExpr(ExplicitCastExpr *E); - void VisitCStyleCastExpr(CStyleCastExpr *E); - void VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - void VisitExtVectorElementExpr(ExtVectorElementExpr *E); - void VisitInitListExpr(InitListExpr *E); - void VisitDesignatedInitExpr(DesignatedInitExpr *E); - void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); - void VisitVAArgExpr(VAArgExpr *E); - void VisitAddrLabelExpr(AddrLabelExpr *E); - void VisitStmtExpr(StmtExpr *E); - void VisitTypesCompatibleExpr(TypesCompatibleExpr *E); - void VisitChooseExpr(ChooseExpr *E); - void VisitGNUNullExpr(GNUNullExpr *E); - void VisitShuffleVectorExpr(ShuffleVectorExpr *E); - void VisitBlockExpr(BlockExpr *E); - void VisitBlockDeclRefExpr(BlockDeclRefExpr *E); - void VisitObjCStringLiteral(ObjCStringLiteral *E); - void VisitObjCEncodeExpr(ObjCEncodeExpr *E); - void VisitObjCSelectorExpr(ObjCSelectorExpr *E); - void VisitObjCProtocolExpr(ObjCProtocolExpr *E); - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E); - void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E); - void VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E); - void VisitObjCMessageExpr(ObjCMessageExpr *E); - void VisitObjCSuperExpr(ObjCSuperExpr *E); - void VisitObjCIsaExpr(ObjCIsaExpr *E); - - void VisitObjCForCollectionStmt(ObjCForCollectionStmt *); - void VisitObjCAtCatchStmt(ObjCAtCatchStmt *); - void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); - void VisitObjCAtTryStmt(ObjCAtTryStmt *); - void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); - void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); - - // C++ Statements - void VisitCXXCatchStmt(CXXCatchStmt *S); - void VisitCXXTryStmt(CXXTryStmt *S); - - void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); - void VisitCXXConstructExpr(CXXConstructExpr *E); - void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); - void VisitCXXNamedCastExpr(CXXNamedCastExpr *E); - void VisitCXXStaticCastExpr(CXXStaticCastExpr *E); - void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E); - void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E); - void VisitCXXConstCastExpr(CXXConstCastExpr *E); - void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E); - void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); - void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); - void VisitCXXTypeidExpr(CXXTypeidExpr *E); - void VisitCXXThisExpr(CXXThisExpr *E); - void VisitCXXThrowExpr(CXXThrowExpr *E); - void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); - void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); - void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E); - - void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); - void VisitCXXNewExpr(CXXNewExpr *E); - void VisitCXXDeleteExpr(CXXDeleteExpr *E); - void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); - - void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); - - void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); - void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); - void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); - - void VisitOverloadExpr(OverloadExpr *E); - void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); - void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); - - void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); - }; -} - -void PCHStmtReader:: -ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList, - unsigned NumTemplateArgs) { - TemplateArgumentListInfo ArgInfo; - ArgInfo.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - ArgInfo.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx)); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument( - Reader.ReadTemplateArgumentLoc(DeclsCursor, Record, Idx)); - ArgList.initializeFrom(ArgInfo); -} - -void PCHStmtReader::VisitStmt(Stmt *S) { - assert(Idx == NumStmtFields && "Incorrect statement field count"); -} - -void PCHStmtReader::VisitNullStmt(NullStmt *S) { - VisitStmt(S); - S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) { - VisitStmt(S); - llvm::SmallVector<Stmt *, 16> Stmts; - unsigned NumStmts = Record[Idx++]; - while (NumStmts--) - Stmts.push_back(Reader.ReadSubStmt()); - S->setStmts(*Reader.getContext(), Stmts.data(), Stmts.size()); - S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitSwitchCase(SwitchCase *S) { - VisitStmt(S); - Reader.RecordSwitchCaseID(S, Record[Idx++]); -} - -void PCHStmtReader::VisitCaseStmt(CaseStmt *S) { - VisitSwitchCase(S); - S->setLHS(Reader.ReadSubExpr()); - S->setRHS(Reader.ReadSubExpr()); - S->setSubStmt(Reader.ReadSubStmt()); - S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setEllipsisLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) { - VisitSwitchCase(S); - S->setSubStmt(Reader.ReadSubStmt()); - S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); - S->setID(Reader.GetIdentifierInfo(Record, Idx)); - S->setSubStmt(Reader.ReadSubStmt()); - S->setIdentLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - Reader.RecordLabelStmt(S, Record[Idx++]); -} - -void PCHStmtReader::VisitIfStmt(IfStmt *S) { - VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setCond(Reader.ReadSubExpr()); - S->setThen(Reader.ReadSubStmt()); - S->setElse(Reader.ReadSubStmt()); - S->setIfLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setElseLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) { - VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setCond(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - SwitchCase *PrevSC = 0; - for (unsigned N = Record.size(); Idx != N; ++Idx) { - SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]); - if (PrevSC) - PrevSC->setNextSwitchCase(SC); - else - S->setSwitchCaseList(SC); - - // Retain this SwitchCase, since SwitchStmt::addSwitchCase() would - // normally retain it (but we aren't calling addSwitchCase). - SC->Retain(); - PrevSC = SC; - } -} - -void PCHStmtReader::VisitWhileStmt(WhileStmt *S) { - VisitStmt(S); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setCond(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitDoStmt(DoStmt *S) { - VisitStmt(S); - S->setCond(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setDoLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitForStmt(ForStmt *S) { - VisitStmt(S); - S->setInit(Reader.ReadSubStmt()); - S->setCond(Reader.ReadSubExpr()); - S->setConditionVariable(*Reader.getContext(), - cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setInc(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitGotoStmt(GotoStmt *S) { - VisitStmt(S); - Reader.SetLabelOf(S, Record[Idx++]); - S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - VisitStmt(S); - S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setTarget(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitContinueStmt(ContinueStmt *S) { - VisitStmt(S); - S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitBreakStmt(BreakStmt *S) { - VisitStmt(S); - S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitReturnStmt(ReturnStmt *S) { - VisitStmt(S); - S->setRetValue(Reader.ReadSubExpr()); - S->setReturnLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setNRVOCandidate(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHStmtReader::VisitDeclStmt(DeclStmt *S) { - VisitStmt(S); - S->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - - if (Idx + 1 == Record.size()) { - // Single declaration - S->setDeclGroup(DeclGroupRef(Reader.GetDecl(Record[Idx++]))); - } else { - llvm::SmallVector<Decl *, 16> Decls; - Decls.reserve(Record.size() - Idx); - for (unsigned N = Record.size(); Idx != N; ++Idx) - Decls.push_back(Reader.GetDecl(Record[Idx])); - S->setDeclGroup(DeclGroupRef(DeclGroup::Create(*Reader.getContext(), - Decls.data(), - Decls.size()))); - } -} - -void PCHStmtReader::VisitAsmStmt(AsmStmt *S) { - VisitStmt(S); - unsigned NumOutputs = Record[Idx++]; - unsigned NumInputs = Record[Idx++]; - unsigned NumClobbers = Record[Idx++]; - S->setAsmLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setVolatile(Record[Idx++]); - S->setSimple(Record[Idx++]); - S->setMSAsm(Record[Idx++]); - - S->setAsmString(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); - - // Outputs and inputs - llvm::SmallVector<IdentifierInfo *, 16> Names; - llvm::SmallVector<StringLiteral*, 16> Constraints; - llvm::SmallVector<Stmt*, 16> Exprs; - for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) { - Names.push_back(Reader.GetIdentifierInfo(Record, Idx)); - Constraints.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); - Exprs.push_back(Reader.ReadSubStmt()); - } - - // Constraints - llvm::SmallVector<StringLiteral*, 16> Clobbers; - for (unsigned I = 0; I != NumClobbers; ++I) - Clobbers.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt())); - - S->setOutputsAndInputsAndClobbers(*Reader.getContext(), - Names.data(), Constraints.data(), - Exprs.data(), NumOutputs, NumInputs, - Clobbers.data(), NumClobbers); -} - -void PCHStmtReader::VisitExpr(Expr *E) { - VisitStmt(E); - E->setType(Reader.GetType(Record[Idx++])); - E->setTypeDependent(Record[Idx++]); - E->setValueDependent(Record[Idx++]); - assert(Idx == NumExprFields && "Incorrect expression field count"); -} - -void PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]); -} - -void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) { - VisitExpr(E); - - bool HasQualifier = Record[Idx++]; - unsigned NumTemplateArgs = Record[Idx++]; - - E->DecoratedD.setInt((HasQualifier? DeclRefExpr::HasQualifierFlag : 0) | - (NumTemplateArgs ? DeclRefExpr::HasExplicitTemplateArgumentListFlag : 0)); - - if (HasQualifier) { - E->getNameQualifier()->NNS = Reader.ReadNestedNameSpecifier(Record, Idx); - E->getNameQualifier()->Range = Reader.ReadSourceRange(Record, Idx); - } - - if (NumTemplateArgs) - ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(), - NumTemplateArgs); - - E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++]))); - // FIXME: read DeclarationNameLoc. - E->setLocation(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setValue(Reader.ReadAPInt(Record, Idx)); -} - -void PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) { - VisitExpr(E); - E->setValue(Reader.ReadAPFloat(Record, Idx)); - E->setExact(Record[Idx++]); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) { - VisitExpr(E); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitStringLiteral(StringLiteral *E) { - VisitExpr(E); - unsigned Len = Record[Idx++]; - assert(Record[Idx] == E->getNumConcatenated() && - "Wrong number of concatenated tokens!"); - ++Idx; - E->setWide(Record[Idx++]); - - // Read string data - llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); - E->setString(*Reader.getContext(), Str.str()); - Idx += Len; - - // Read source locations - for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) - E->setStrTokenLoc(I, SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) { - VisitExpr(E); - E->setValue(Record[Idx++]); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setWide(Record[Idx++]); -} - -void PCHStmtReader::VisitParenExpr(ParenExpr *E) { - VisitExpr(E); - E->setLParen(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParen(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitParenListExpr(ParenListExpr *E) { - VisitExpr(E); - unsigned NumExprs = Record[Idx++]; - E->Exprs = new (*Reader.getContext()) Stmt*[NumExprs]; - for (unsigned i = 0; i != NumExprs; ++i) - E->Exprs[i] = Reader.ReadSubStmt(); - E->NumExprs = NumExprs; - E->LParenLoc = Reader.ReadSourceLocation(Record, Idx); - E->RParenLoc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHStmtReader::VisitUnaryOperator(UnaryOperator *E) { - VisitExpr(E); - E->setSubExpr(Reader.ReadSubExpr()); - E->setOpcode((UnaryOperator::Opcode)Record[Idx++]); - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { - typedef OffsetOfExpr::OffsetOfNode Node; - VisitExpr(E); - assert(E->getNumComponents() == Record[Idx]); - ++Idx; - assert(E->getNumExpressions() == Record[Idx]); - ++Idx; - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]); - SourceLocation Start = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation End = SourceLocation::getFromRawEncoding(Record[Idx++]); - switch (Kind) { - case Node::Array: - E->setComponent(I, Node(Start, Record[Idx++], End)); - break; - - case Node::Field: - E->setComponent(I, - Node(Start, - dyn_cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])), - End)); - break; - - case Node::Identifier: - E->setComponent(I, Node(Start, Reader.GetIdentifier(Record[Idx++]), End)); - break; - - case Node::Base: { - CXXBaseSpecifier *Base = new (*Reader.getContext()) CXXBaseSpecifier(); - *Base = Reader.ReadCXXBaseSpecifier(DeclsCursor, Record, Idx); - E->setComponent(I, Node(Base)); - break; - } - } - } - - for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) - E->setIndexExpr(I, Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { - VisitExpr(E); - E->setSizeof(Record[Idx++]); - if (Record[Idx] == 0) { - E->setArgument(Reader.ReadSubExpr()); - ++Idx; - } else { - E->setArgument(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - } - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - VisitExpr(E); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCallExpr(CallExpr *E) { - VisitExpr(E); - E->setNumArgs(*Reader.getContext(), Record[Idx++]); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setCallee(Reader.ReadSubExpr()); - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, this is fully initialized at creation. - assert(E->getStmtClass() == Stmt::MemberExprClass && - "It's a subclass, we must advance Idx!"); -} - -void PCHStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) { - VisitExpr(E); - E->setBase(Reader.ReadSubExpr()); - E->setIsaMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setArrow(Record[Idx++]); -} - -void PCHStmtReader::VisitCastExpr(CastExpr *E) { - VisitExpr(E); - unsigned NumBaseSpecs = Record[Idx++]; - assert(NumBaseSpecs == E->path_size()); - E->setSubExpr(Reader.ReadSubExpr()); - E->setCastKind((CastExpr::CastKind)Record[Idx++]); - CastExpr::path_iterator BaseI = E->path_begin(); - while (NumBaseSpecs--) { - CXXBaseSpecifier *BaseSpec = new (*Reader.getContext()) CXXBaseSpecifier; - *BaseSpec = Reader.ReadCXXBaseSpecifier(DeclsCursor, Record, Idx); - *BaseI++ = BaseSpec; - } -} - -void PCHStmtReader::VisitBinaryOperator(BinaryOperator *E) { - VisitExpr(E); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setOpcode((BinaryOperator::Opcode)Record[Idx++]); - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - E->setComputationLHSType(Reader.GetType(Record[Idx++])); - E->setComputationResultType(Reader.GetType(Record[Idx++])); -} - -void PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) { - VisitExpr(E); - E->setCond(Reader.ReadSubExpr()); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setQuestionLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) { - VisitCastExpr(E); - E->setCategory(static_cast<ImplicitCastExpr::ResultCategory>(Record[Idx++])); -} - -void PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) { - VisitCastExpr(E); - E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); -} - -void PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) { - VisitExplicitCastExpr(E); - E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - VisitExpr(E); - E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - E->setInitializer(Reader.ReadSubExpr()); - E->setFileScope(Record[Idx++]); -} - -void PCHStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { - VisitExpr(E); - E->setBase(Reader.ReadSubExpr()); - E->setAccessor(Reader.GetIdentifierInfo(Record, Idx)); - E->setAccessorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitInitListExpr(InitListExpr *E) { - VisitExpr(E); - unsigned NumInits = Record[Idx++]; - E->reserveInits(*Reader.getContext(), NumInits); - for (unsigned I = 0; I != NumInits; ++I) - E->updateInit(*Reader.getContext(), I, Reader.ReadSubExpr()); - E->setSyntacticForm(cast_or_null<InitListExpr>(Reader.ReadSubStmt())); - E->setLBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setInitializedFieldInUnion( - cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]))); - E->sawArrayRangeDesignator(Record[Idx++]); -} - -void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - typedef DesignatedInitExpr::Designator Designator; - - VisitExpr(E); - unsigned NumSubExprs = Record[Idx++]; - assert(NumSubExprs == E->getNumSubExprs() && "Wrong number of subexprs"); - for (unsigned I = 0; I != NumSubExprs; ++I) - E->setSubExpr(I, Reader.ReadSubExpr()); - E->setEqualOrColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setGNUSyntax(Record[Idx++]); - - llvm::SmallVector<Designator, 4> Designators; - while (Idx < Record.size()) { - switch ((pch::DesignatorTypes)Record[Idx++]) { - case pch::DESIG_FIELD_DECL: { - FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++])); - SourceLocation DotLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation FieldLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Field->getIdentifier(), DotLoc, - FieldLoc)); - Designators.back().setField(Field); - break; - } - - case pch::DESIG_FIELD_NAME: { - const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx); - SourceLocation DotLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation FieldLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Name, DotLoc, FieldLoc)); - break; - } - - case pch::DESIG_ARRAY: { - unsigned Index = Record[Idx++]; - SourceLocation LBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation RBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc)); - break; - } - - case pch::DESIG_ARRAY_RANGE: { - unsigned Index = Record[Idx++]; - SourceLocation LBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation EllipsisLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation RBracketLoc - = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc, - RBracketLoc)); - break; - } - } - } - E->setDesignators(*Reader.getContext(), - Designators.data(), Designators.size()); -} - -void PCHStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - VisitExpr(E); -} - -void PCHStmtReader::VisitVAArgExpr(VAArgExpr *E) { - VisitExpr(E); - E->setSubExpr(Reader.ReadSubExpr()); - E->setWrittenTypeInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) { - VisitExpr(E); - E->setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - Reader.SetLabelOf(E, Record[Idx++]); -} - -void PCHStmtReader::VisitStmtExpr(StmtExpr *E) { - VisitExpr(E); - E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setSubStmt(cast_or_null<CompoundStmt>(Reader.ReadSubStmt())); -} - -void PCHStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) { - VisitExpr(E); - E->setArgTInfo1(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - E->setArgTInfo2(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitChooseExpr(ChooseExpr *E) { - VisitExpr(E); - E->setCond(Reader.ReadSubExpr()); - E->setLHS(Reader.ReadSubExpr()); - E->setRHS(Reader.ReadSubExpr()); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitGNUNullExpr(GNUNullExpr *E) { - VisitExpr(E); - E->setTokenLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - VisitExpr(E); - llvm::SmallVector<Expr *, 16> Exprs; - unsigned NumExprs = Record[Idx++]; - while (NumExprs--) - Exprs.push_back(Reader.ReadSubExpr()); - E->setExprs(*Reader.getContext(), Exprs.data(), Exprs.size()); - E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitBlockExpr(BlockExpr *E) { - VisitExpr(E); - E->setBlockDecl(cast_or_null<BlockDecl>(Reader.GetDecl(Record[Idx++]))); - E->setHasBlockDeclRefExprs(Record[Idx++]); -} - -void PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - VisitExpr(E); - E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setByRef(Record[Idx++]); - E->setConstQualAdded(Record[Idx++]); - E->setCopyConstructorExpr(Reader.ReadSubExpr()); -} - -//===----------------------------------------------------------------------===// -// Objective-C Expressions and Statements - -void PCHStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) { - VisitExpr(E); - E->setString(cast<StringLiteral>(Reader.ReadSubStmt())); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { - VisitExpr(E); - E->setEncodedTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor,Record,Idx)); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - VisitExpr(E); - E->setSelector(Reader.GetSelector(Record, Idx)); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - VisitExpr(E); - E->setProtocol(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); - E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - VisitExpr(E); - E->setDecl(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setBase(Reader.ReadSubExpr()); - E->setIsArrow(Record[Idx++]); - E->setIsFreeIvar(Record[Idx++]); -} - -void PCHStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - VisitExpr(E); - E->setProperty(cast<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setBase(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E) { - VisitExpr(E); - E->setGetterMethod( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - E->setSetterMethod( - cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - E->setInterfaceDecl( - cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - E->setBase(Reader.ReadSubExpr()); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { - VisitExpr(E); - assert(Record[Idx] == E->getNumArgs()); - ++Idx; - ObjCMessageExpr::ReceiverKind Kind - = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]); - switch (Kind) { - case ObjCMessageExpr::Instance: - E->setInstanceReceiver(Reader.ReadSubExpr()); - break; - - case ObjCMessageExpr::Class: - E->setClassReceiver(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - break; - - case ObjCMessageExpr::SuperClass: - case ObjCMessageExpr::SuperInstance: { - QualType T = Reader.GetType(Record[Idx++]); - SourceLocation SuperLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); - E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance); - break; - } - } - - assert(Kind == E->getReceiverKind()); - - if (Record[Idx++]) - E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - else - E->setSelector(Reader.GetSelector(Record, Idx)); - - E->setLeftLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRightLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitObjCSuperExpr(ObjCSuperExpr *E) { - VisitExpr(E); - E->setLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - VisitStmt(S); - S->setElement(Reader.ReadSubStmt()); - S->setCollection(Reader.ReadSubExpr()); - S->setBody(Reader.ReadSubStmt()); - S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - VisitStmt(S); - S->setCatchBody(Reader.ReadSubStmt()); - S->setCatchParamDecl(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - S->setAtCatchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - VisitStmt(S); - S->setFinallyBody(Reader.ReadSubStmt()); - S->setAtFinallyLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - VisitStmt(S); - assert(Record[Idx] == S->getNumCatchStmts()); - ++Idx; - bool HasFinally = Record[Idx++]; - S->setTryBody(Reader.ReadSubStmt()); - for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) - S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(Reader.ReadSubStmt())); - - if (HasFinally) - S->setFinallyStmt(Reader.ReadSubStmt()); - S->setAtTryLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { - VisitStmt(S); - S->setSynchExpr(Reader.ReadSubStmt()); - S->setSynchBody(Reader.ReadSubStmt()); - S->setAtSynchronizedLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - VisitStmt(S); - S->setThrowExpr(Reader.ReadSubStmt()); - S->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -//===----------------------------------------------------------------------===// -// C++ Expressions and Statements -//===----------------------------------------------------------------------===// - -void PCHStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) { - VisitStmt(S); - S->CatchLoc = Reader.ReadSourceLocation(Record, Idx); - S->ExceptionDecl = cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])); - S->HandlerBlock = Reader.ReadSubStmt(); -} - -void PCHStmtReader::VisitCXXTryStmt(CXXTryStmt *S) { - VisitStmt(S); - assert(Record[Idx] == S->getNumHandlers() && "NumStmtFields is wrong ?"); - ++Idx; - S->TryLoc = Reader.ReadSourceLocation(Record, Idx); - S->getStmts()[0] = Reader.ReadSubStmt(); - for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i) - S->getStmts()[i + 1] = Reader.ReadSubStmt(); -} - -void PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - VisitCallExpr(E); - E->setOperator((OverloadedOperatorKind)Record[Idx++]); -} - -void PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { - VisitExpr(E); - E->NumArgs = Record[Idx++]; - if (E->NumArgs) - E->Args = new (*Reader.getContext()) Stmt*[E->NumArgs]; - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); - E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++]))); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setElidable(Record[Idx++]); - E->setRequiresZeroInitialization(Record[Idx++]); - E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); -} - -void PCHStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { - VisitCXXConstructExpr(E); - E->TyBeginLoc = Reader.ReadSourceLocation(Record, Idx); - E->RParenLoc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - VisitExplicitCastExpr(E); - E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -void PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { - VisitExplicitCastExpr(E); - E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - VisitExpr(E); - E->setValue(Record[Idx++]); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - VisitExpr(E); - E->setSourceRange(Reader.ReadSourceRange(Record, Idx)); - if (E->isTypeOperand()) { // typeid(int) - E->setTypeOperandSourceInfo( - Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - return; - } - - // typeid(42+2) - E->setExprOperand(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitCXXThisExpr(CXXThisExpr *E) { - VisitExpr(E); - E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setImplicit(Record[Idx++]); -} - -void PCHStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) { - VisitExpr(E); - E->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - VisitExpr(E); - - assert(Record[Idx] == E->Param.getInt() && "We messed up at creation ?"); - ++Idx; // HasOtherExprStored and SubExpr was handled during creation. - E->Param.setPointer(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - E->Loc = Reader.ReadSourceLocation(Record, Idx); -} - -void PCHStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - VisitExpr(E); - E->setTemporary(Reader.ReadCXXTemporary(Record, Idx)); - E->setSubExpr(Reader.ReadSubExpr()); -} - -void PCHStmtReader::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) { - VisitExpr(E); - E->SubExpr = Reader.ReadSubExpr(); - E->ExtendsLifetime = Record[Idx++]; - E->RequiresTemporaryCopy = Record[Idx++]; -} - -void PCHStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - VisitExpr(E); - E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { - VisitExpr(E); - E->setGlobalNew(Record[Idx++]); - E->setHasInitializer(Record[Idx++]); - bool isArray = Record[Idx++]; - unsigned NumPlacementArgs = Record[Idx++]; - unsigned NumCtorArgs = Record[Idx++]; - E->setOperatorNew(cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setOperatorDelete( - cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setConstructor( - cast_or_null<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++]))); - SourceRange TypeIdParens; - TypeIdParens.setBegin(SourceLocation::getFromRawEncoding(Record[Idx++])); - TypeIdParens.setEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->TypeIdParens = TypeIdParens; - E->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - - E->AllocateArgsArray(*Reader.getContext(), isArray, NumPlacementArgs, - NumCtorArgs); - - // Install all the subexpressions. - for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end(); - I != e; ++I) - *I = Reader.ReadSubStmt(); -} - -void PCHStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - VisitExpr(E); - E->setGlobalDelete(Record[Idx++]); - E->setArrayForm(Record[Idx++]); - E->setOperatorDelete( - cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); - E->setArgument(Reader.ReadSubExpr()); - E->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -void PCHStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { - VisitExpr(E); - - E->setBase(Reader.ReadSubExpr()); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setScopeTypeInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); - E->setColonColonLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setTildeLoc(Reader.ReadSourceLocation(Record, Idx)); - - IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx); - if (II) - E->setDestroyedType(II, Reader.ReadSourceLocation(Record, Idx)); - else - E->setDestroyedType(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); -} - -void PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - VisitExpr(E); - unsigned NumTemps = Record[Idx++]; - if (NumTemps) { - E->setNumTemporaries(*Reader.getContext(), NumTemps); - for (unsigned i = 0; i != NumTemps; ++i) - E->setTemporary(i, Reader.ReadCXXTemporary(Record, Idx)); - } - E->setSubExpr(Reader.ReadSubExpr()); -} - -void -PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ - VisitExpr(E); - - unsigned NumTemplateArgs = Record[Idx++]; - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && - "Read wrong record during creation ?"); - if (E->hasExplicitTemplateArgs()) - ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(), - NumTemplateArgs); - - E->setBase(Reader.ReadSubExpr()); - E->setBaseType(Reader.GetType(Record[Idx++])); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setFirstQualifierFoundInScope( - cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]))); - // FIXME: read whole DeclarationNameInfo. - E->setMember(Reader.ReadDeclarationName(Record, Idx)); - E->setMemberLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void -PCHStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - VisitExpr(E); - - unsigned NumTemplateArgs = Record[Idx++]; - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && - "Read wrong record during creation ?"); - if (E->hasExplicitTemplateArgs()) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - NumTemplateArgs); - - // FIXME: read whole DeclarationNameInfo. - E->setDeclName(Reader.ReadDeclarationName(Record, Idx)); - E->setLocation(Reader.ReadSourceLocation(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); -} - -void -PCHStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { - VisitExpr(E); - assert(Record[Idx] == E->arg_size() && "Read wrong record during creation ?"); - ++Idx; // NumArgs; - for (unsigned I = 0, N = E->arg_size(); I != N; ++I) - E->setArg(I, Reader.ReadSubExpr()); - E->setTypeBeginLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setTypeAsWritten(Reader.GetType(Record[Idx++])); - E->setLParenLoc(Reader.ReadSourceLocation(Record, Idx)); - E->setRParenLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) { - VisitExpr(E); - - unsigned NumTemplateArgs = Record[Idx++]; - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() && - "Read wrong record during creation ?"); - if (E->hasExplicitTemplateArgs()) - ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), - NumTemplateArgs); - - unsigned NumDecls = Record[Idx++]; - UnresolvedSet<8> Decls; - for (unsigned i = 0; i != NumDecls; ++i) { - NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); - AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Decls.addDecl(D, AS); - } - E->initializeResults(*Reader.getContext(), Decls.begin(), Decls.end()); - - // FIXME: read whole DeclarationNameInfo. - E->setName(Reader.ReadDeclarationName(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - E->setNameLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - VisitOverloadExpr(E); - E->setArrow(Record[Idx++]); - E->setHasUnresolvedUsing(Record[Idx++]); - E->setBase(Reader.ReadSubExpr()); - E->setBaseType(Reader.GetType(Record[Idx++])); - E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx)); -} - -void PCHStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - VisitOverloadExpr(E); - E->setRequiresADL(Record[Idx++]); - E->setOverloaded(Record[Idx++]); - E->setNamingClass(cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]))); -} - -void PCHStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - VisitExpr(E); - E->UTT = (UnaryTypeTrait)Record[Idx++]; - SourceRange Range = Reader.ReadSourceRange(Record, Idx); - E->Loc = Range.getBegin(); - E->RParen = Range.getEnd(); - E->QueriedType = Reader.GetType(Record[Idx++]); -} - -Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { - switch (ReadingKind) { - case Read_Decl: - case Read_Type: - return ReadStmtFromStream(Cursor); - case Read_Stmt: - return ReadSubStmt(); - } - - llvm_unreachable("ReadingKind not set ?"); - return 0; -} - -Expr *PCHReader::ReadExpr(llvm::BitstreamCursor &Cursor) { - return cast_or_null<Expr>(ReadStmt(Cursor)); -} - -Expr *PCHReader::ReadSubExpr() { - return cast_or_null<Expr>(ReadSubStmt()); -} - -// Within the bitstream, expressions are stored in Reverse Polish -// Notation, with each of the subexpressions preceding the -// expression they are stored in. Subexpressions are stored from last to first. -// To evaluate expressions, we continue reading expressions and placing them on -// the stack, with expressions having operands removing those operands from the -// stack. Evaluation terminates when we see a STMT_STOP record, and -// the single remaining expression on the stack is our result. -Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) { - - ReadingKindTracker ReadingKind(Read_Stmt, *this); - -#ifndef NDEBUG - unsigned PrevNumStmts = StmtStack.size(); -#endif - - RecordData Record; - unsigned Idx; - PCHStmtReader Reader(*this, Cursor, Record, Idx); - Stmt::EmptyShell Empty; - - while (true) { - unsigned Code = Cursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Cursor.ReadBlockEnd()) { - Error("error at end of block in PCH file"); - return 0; - } - break; - } - - 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 0; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Cursor.ReadAbbrevRecord(); - continue; - } - - Stmt *S = 0; - Idx = 0; - Record.clear(); - bool Finished = false; - switch ((pch::StmtCode)Cursor.ReadRecord(Code, Record)) { - case pch::STMT_STOP: - Finished = true; - break; - - case pch::STMT_NULL_PTR: - S = 0; - break; - - case pch::STMT_NULL: - S = new (Context) NullStmt(Empty); - break; - - case pch::STMT_COMPOUND: - S = new (Context) CompoundStmt(Empty); - break; - - case pch::STMT_CASE: - S = new (Context) CaseStmt(Empty); - break; - - case pch::STMT_DEFAULT: - S = new (Context) DefaultStmt(Empty); - break; - - case pch::STMT_LABEL: - S = new (Context) LabelStmt(Empty); - break; - - case pch::STMT_IF: - S = new (Context) IfStmt(Empty); - break; - - case pch::STMT_SWITCH: - S = new (Context) SwitchStmt(Empty); - break; - - case pch::STMT_WHILE: - S = new (Context) WhileStmt(Empty); - break; - - case pch::STMT_DO: - S = new (Context) DoStmt(Empty); - break; - - case pch::STMT_FOR: - S = new (Context) ForStmt(Empty); - break; - - case pch::STMT_GOTO: - S = new (Context) GotoStmt(Empty); - break; - - case pch::STMT_INDIRECT_GOTO: - S = new (Context) IndirectGotoStmt(Empty); - break; - - case pch::STMT_CONTINUE: - S = new (Context) ContinueStmt(Empty); - break; - - case pch::STMT_BREAK: - S = new (Context) BreakStmt(Empty); - break; - - case pch::STMT_RETURN: - S = new (Context) ReturnStmt(Empty); - break; - - case pch::STMT_DECL: - S = new (Context) DeclStmt(Empty); - break; - - case pch::STMT_ASM: - S = new (Context) AsmStmt(Empty); - break; - - case pch::EXPR_PREDEFINED: - S = new (Context) PredefinedExpr(Empty); - break; - - case pch::EXPR_DECL_REF: - S = DeclRefExpr::CreateEmpty(*Context, - /*HasQualifier=*/Record[PCHStmtReader::NumExprFields], - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields + 1]); - break; - - case pch::EXPR_INTEGER_LITERAL: - S = new (Context) IntegerLiteral(Empty); - break; - - case pch::EXPR_FLOATING_LITERAL: - S = new (Context) FloatingLiteral(Empty); - break; - - case pch::EXPR_IMAGINARY_LITERAL: - S = new (Context) ImaginaryLiteral(Empty); - break; - - case pch::EXPR_STRING_LITERAL: - S = StringLiteral::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields + 1]); - break; - - case pch::EXPR_CHARACTER_LITERAL: - S = new (Context) CharacterLiteral(Empty); - break; - - case pch::EXPR_PAREN: - S = new (Context) ParenExpr(Empty); - break; - - case pch::EXPR_PAREN_LIST: - S = new (Context) ParenListExpr(Empty); - break; - - case pch::EXPR_UNARY_OPERATOR: - S = new (Context) UnaryOperator(Empty); - break; - - case pch::EXPR_OFFSETOF: - S = OffsetOfExpr::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields], - Record[PCHStmtReader::NumExprFields + 1]); - break; - - case pch::EXPR_SIZEOF_ALIGN_OF: - S = new (Context) SizeOfAlignOfExpr(Empty); - break; - - case pch::EXPR_ARRAY_SUBSCRIPT: - S = new (Context) ArraySubscriptExpr(Empty); - break; - - case pch::EXPR_CALL: - S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty); - break; - - case pch::EXPR_MEMBER: { - // We load everything here and fully initialize it at creation. - // That way we can use MemberExpr::Create and don't have to duplicate its - // logic with a MemberExpr::CreateEmpty. - - assert(Idx == 0); - NestedNameSpecifier *NNS = 0; - SourceRange QualifierRange; - if (Record[Idx++]) { // HasQualifier. - NNS = ReadNestedNameSpecifier(Record, Idx); - QualifierRange = ReadSourceRange(Record, Idx); - } - - TemplateArgumentListInfo ArgInfo; - unsigned NumTemplateArgs = Record[Idx++]; - if (NumTemplateArgs) { - ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx)); - ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx)); - for (unsigned i = 0; i != NumTemplateArgs; ++i) - ArgInfo.addArgument(ReadTemplateArgumentLoc(Cursor, Record, Idx)); - } - - NamedDecl *FoundD = cast_or_null<NamedDecl>(GetDecl(Record[Idx++])); - AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS); - - QualType T = GetType(Record[Idx++]); - Expr *Base = ReadSubExpr(); - ValueDecl *MemberD = cast<ValueDecl>(GetDecl(Record[Idx++])); - // FIXME: read DeclarationNameLoc. - SourceLocation MemberLoc = ReadSourceLocation(Record, Idx); - DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc); - bool IsArrow = Record[Idx++]; - - S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange, - MemberD, FoundDecl, MemberNameInfo, - NumTemplateArgs ? &ArgInfo : 0, T); - break; - } - - case pch::EXPR_BINARY_OPERATOR: - S = new (Context) BinaryOperator(Empty); - break; - - case pch::EXPR_COMPOUND_ASSIGN_OPERATOR: - S = new (Context) CompoundAssignOperator(Empty); - break; - - case pch::EXPR_CONDITIONAL_OPERATOR: - S = new (Context) ConditionalOperator(Empty); - break; - - case pch::EXPR_IMPLICIT_CAST: - S = ImplicitCastExpr::CreateEmpty(*Context, - /*PathSize*/ Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CSTYLE_CAST: - S = CStyleCastExpr::CreateEmpty(*Context, - /*PathSize*/ Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_COMPOUND_LITERAL: - S = new (Context) CompoundLiteralExpr(Empty); - break; - - case pch::EXPR_EXT_VECTOR_ELEMENT: - S = new (Context) ExtVectorElementExpr(Empty); - break; - - case pch::EXPR_INIT_LIST: - S = new (Context) InitListExpr(*getContext(), Empty); - break; - - case pch::EXPR_DESIGNATED_INIT: - S = DesignatedInitExpr::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields] - 1); - - break; - - case pch::EXPR_IMPLICIT_VALUE_INIT: - S = new (Context) ImplicitValueInitExpr(Empty); - break; - - case pch::EXPR_VA_ARG: - S = new (Context) VAArgExpr(Empty); - break; - - case pch::EXPR_ADDR_LABEL: - S = new (Context) AddrLabelExpr(Empty); - break; - - case pch::EXPR_STMT: - S = new (Context) StmtExpr(Empty); - break; - - case pch::EXPR_TYPES_COMPATIBLE: - S = new (Context) TypesCompatibleExpr(Empty); - break; - - case pch::EXPR_CHOOSE: - S = new (Context) ChooseExpr(Empty); - break; - - case pch::EXPR_GNU_NULL: - S = new (Context) GNUNullExpr(Empty); - break; - - case pch::EXPR_SHUFFLE_VECTOR: - S = new (Context) ShuffleVectorExpr(Empty); - break; - - case pch::EXPR_BLOCK: - S = new (Context) BlockExpr(Empty); - break; - - case pch::EXPR_BLOCK_DECL_REF: - S = new (Context) BlockDeclRefExpr(Empty); - break; - - case pch::EXPR_OBJC_STRING_LITERAL: - S = new (Context) ObjCStringLiteral(Empty); - break; - case pch::EXPR_OBJC_ENCODE: - S = new (Context) ObjCEncodeExpr(Empty); - break; - case pch::EXPR_OBJC_SELECTOR_EXPR: - S = new (Context) ObjCSelectorExpr(Empty); - break; - case pch::EXPR_OBJC_PROTOCOL_EXPR: - S = new (Context) ObjCProtocolExpr(Empty); - break; - case pch::EXPR_OBJC_IVAR_REF_EXPR: - S = new (Context) ObjCIvarRefExpr(Empty); - break; - case pch::EXPR_OBJC_PROPERTY_REF_EXPR: - S = new (Context) ObjCPropertyRefExpr(Empty); - break; - case pch::EXPR_OBJC_KVC_REF_EXPR: - S = new (Context) ObjCImplicitSetterGetterRefExpr(Empty); - break; - case pch::EXPR_OBJC_MESSAGE_EXPR: - S = ObjCMessageExpr::CreateEmpty(*Context, - Record[PCHStmtReader::NumExprFields]); - break; - case pch::EXPR_OBJC_SUPER_EXPR: - S = new (Context) ObjCSuperExpr(Empty); - break; - case pch::EXPR_OBJC_ISA: - S = new (Context) ObjCIsaExpr(Empty); - break; - case pch::STMT_OBJC_FOR_COLLECTION: - S = new (Context) ObjCForCollectionStmt(Empty); - break; - case pch::STMT_OBJC_CATCH: - S = new (Context) ObjCAtCatchStmt(Empty); - break; - case pch::STMT_OBJC_FINALLY: - S = new (Context) ObjCAtFinallyStmt(Empty); - break; - case pch::STMT_OBJC_AT_TRY: - S = ObjCAtTryStmt::CreateEmpty(*Context, - Record[PCHStmtReader::NumStmtFields], - Record[PCHStmtReader::NumStmtFields + 1]); - break; - case pch::STMT_OBJC_AT_SYNCHRONIZED: - S = new (Context) ObjCAtSynchronizedStmt(Empty); - break; - case pch::STMT_OBJC_AT_THROW: - S = new (Context) ObjCAtThrowStmt(Empty); - break; - - case pch::STMT_CXX_CATCH: - S = new (Context) CXXCatchStmt(Empty); - break; - - case pch::STMT_CXX_TRY: - S = CXXTryStmt::Create(*Context, Empty, - /*NumHandlers=*/Record[PCHStmtReader::NumStmtFields]); - break; - - case pch::EXPR_CXX_OPERATOR_CALL: - S = new (Context) CXXOperatorCallExpr(*Context, Empty); - break; - - case pch::EXPR_CXX_MEMBER_CALL: - S = new (Context) CXXMemberCallExpr(*Context, Empty); - break; - - case pch::EXPR_CXX_CONSTRUCT: - S = new (Context) CXXConstructExpr(Empty); - break; - - case pch::EXPR_CXX_TEMPORARY_OBJECT: - S = new (Context) CXXTemporaryObjectExpr(Empty); - break; - - case pch::EXPR_CXX_STATIC_CAST: - S = CXXStaticCastExpr::CreateEmpty(*Context, - /*PathSize*/ Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_DYNAMIC_CAST: - S = CXXDynamicCastExpr::CreateEmpty(*Context, - /*PathSize*/ Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_REINTERPRET_CAST: - S = CXXReinterpretCastExpr::CreateEmpty(*Context, - /*PathSize*/ Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_CONST_CAST: - S = CXXConstCastExpr::CreateEmpty(*Context); - break; - - case pch::EXPR_CXX_FUNCTIONAL_CAST: - S = CXXFunctionalCastExpr::CreateEmpty(*Context, - /*PathSize*/ Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_BOOL_LITERAL: - S = new (Context) CXXBoolLiteralExpr(Empty); - break; - - case pch::EXPR_CXX_NULL_PTR_LITERAL: - S = new (Context) CXXNullPtrLiteralExpr(Empty); - break; - case pch::EXPR_CXX_TYPEID_EXPR: - S = new (Context) CXXTypeidExpr(Empty, true); - break; - case pch::EXPR_CXX_TYPEID_TYPE: - S = new (Context) CXXTypeidExpr(Empty, false); - break; - case pch::EXPR_CXX_THIS: - S = new (Context) CXXThisExpr(Empty); - break; - case pch::EXPR_CXX_THROW: - S = new (Context) CXXThrowExpr(Empty); - break; - case pch::EXPR_CXX_DEFAULT_ARG: { - bool HasOtherExprStored = Record[PCHStmtReader::NumExprFields]; - if (HasOtherExprStored) { - Expr *SubExpr = ReadSubExpr(); - S = CXXDefaultArgExpr::Create(*Context, SourceLocation(), 0, SubExpr); - } else - S = new (Context) CXXDefaultArgExpr(Empty); - break; - } - case pch::EXPR_CXX_BIND_TEMPORARY: - S = new (Context) CXXBindTemporaryExpr(Empty); - break; - case pch::EXPR_CXX_BIND_REFERENCE: - S = new (Context) CXXBindReferenceExpr(Empty); - break; - - case pch::EXPR_CXX_SCALAR_VALUE_INIT: - S = new (Context) CXXScalarValueInitExpr(Empty); - break; - case pch::EXPR_CXX_NEW: - S = new (Context) CXXNewExpr(Empty); - break; - case pch::EXPR_CXX_DELETE: - S = new (Context) CXXDeleteExpr(Empty); - break; - case pch::EXPR_CXX_PSEUDO_DESTRUCTOR: - S = new (Context) CXXPseudoDestructorExpr(Empty); - break; - - case pch::EXPR_CXX_EXPR_WITH_TEMPORARIES: - S = new (Context) CXXExprWithTemporaries(Empty); - break; - - case pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER: - S = CXXDependentScopeMemberExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF: - S = DependentScopeDeclRefExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNRESOLVED_CONSTRUCT: - S = CXXUnresolvedConstructExpr::CreateEmpty(*Context, - /*NumArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNRESOLVED_MEMBER: - S = UnresolvedMemberExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNRESOLVED_LOOKUP: - S = UnresolvedLookupExpr::CreateEmpty(*Context, - /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]); - break; - - case pch::EXPR_CXX_UNARY_TYPE_TRAIT: - S = new (Context) UnaryTypeTraitExpr(Empty); - break; - } - - // We hit a STMT_STOP, so we're done with this expression. - if (Finished) - break; - - ++NumStatementsRead; - - if (S) - Reader.Visit(S); - - assert(Idx == Record.size() && "Invalid deserialization of statement"); - StmtStack.push_back(S); - } - -#ifndef NDEBUG - assert(StmtStack.size() > PrevNumStmts && "Read too many sub stmts!"); - assert(StmtStack.size() == PrevNumStmts + 1 && "Extra expressions on stack!"); -#endif - - return StmtStack.pop_back_val(); -} diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp deleted file mode 100644 index 76fd5528dc8..00000000000 --- a/clang/lib/Frontend/PCHWriter.cpp +++ /dev/null @@ -1,3094 +0,0 @@ -//===--- PCHWriter.cpp - Precompiled Headers Writer -----------------------===// -// -// 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 PCHWriter class, which writes a precompiled header. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHWriter.h" -#include "clang/Sema/Sema.h" -#include "clang/Sema/IdentifierResolver.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclContextInternals.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLocVisitor.h" -#include "clang/Frontend/PCHReader.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/OnDiskHashTable.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/SourceManagerInternals.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/System/Path.h" -#include <cstdio> -using namespace clang; - -template <typename T, typename Allocator> -T *data(std::vector<T, Allocator> &v) { - return v.empty() ? 0 : &v.front(); -} -template <typename T, typename Allocator> -const T *data(const std::vector<T, Allocator> &v) { - return v.empty() ? 0 : &v.front(); -} - -//===----------------------------------------------------------------------===// -// Type serialization -//===----------------------------------------------------------------------===// - -namespace { - class PCHTypeWriter { - PCHWriter &Writer; - PCHWriter::RecordData &Record; - - public: - /// \brief Type code that corresponds to the record generated. - pch::TypeCode Code; - - PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) - : Writer(Writer), Record(Record), Code(pch::TYPE_EXT_QUAL) { } - - void VisitArrayType(const ArrayType *T); - void VisitFunctionType(const FunctionType *T); - void VisitTagType(const TagType *T); - -#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T); -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - }; -} - -void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) { - assert(false && "Built-in types are never serialized"); -} - -void PCHTypeWriter::VisitComplexType(const ComplexType *T) { - Writer.AddTypeRef(T->getElementType(), Record); - Code = pch::TYPE_COMPLEX; -} - -void PCHTypeWriter::VisitPointerType(const PointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_POINTER; -} - -void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_BLOCK_POINTER; -} - -void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_LVALUE_REFERENCE; -} - -void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_RVALUE_REFERENCE; -} - -void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Writer.AddTypeRef(QualType(T->getClass(), 0), Record); - Code = pch::TYPE_MEMBER_POINTER; -} - -void PCHTypeWriter::VisitArrayType(const ArrayType *T) { - Writer.AddTypeRef(T->getElementType(), Record); - Record.push_back(T->getSizeModifier()); // FIXME: stable values - Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values -} - -void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { - VisitArrayType(T); - Writer.AddAPInt(T->getSize(), Record); - Code = pch::TYPE_CONSTANT_ARRAY; -} - -void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { - VisitArrayType(T); - Code = pch::TYPE_INCOMPLETE_ARRAY; -} - -void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { - VisitArrayType(T); - Writer.AddSourceLocation(T->getLBracketLoc(), Record); - Writer.AddSourceLocation(T->getRBracketLoc(), Record); - Writer.AddStmt(T->getSizeExpr()); - Code = pch::TYPE_VARIABLE_ARRAY; -} - -void PCHTypeWriter::VisitVectorType(const VectorType *T) { - Writer.AddTypeRef(T->getElementType(), Record); - Record.push_back(T->getNumElements()); - Record.push_back(T->getAltiVecSpecific()); - Code = pch::TYPE_VECTOR; -} - -void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) { - VisitVectorType(T); - Code = pch::TYPE_EXT_VECTOR; -} - -void PCHTypeWriter::VisitFunctionType(const FunctionType *T) { - Writer.AddTypeRef(T->getResultType(), Record); - FunctionType::ExtInfo C = T->getExtInfo(); - Record.push_back(C.getNoReturn()); - Record.push_back(C.getRegParm()); - // FIXME: need to stabilize encoding of calling convention... - Record.push_back(C.getCC()); -} - -void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { - VisitFunctionType(T); - Code = pch::TYPE_FUNCTION_NO_PROTO; -} - -void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { - VisitFunctionType(T); - Record.push_back(T->getNumArgs()); - for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I) - Writer.AddTypeRef(T->getArgType(I), Record); - Record.push_back(T->isVariadic()); - Record.push_back(T->getTypeQuals()); - Record.push_back(T->hasExceptionSpec()); - Record.push_back(T->hasAnyExceptionSpec()); - Record.push_back(T->getNumExceptions()); - for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) - Writer.AddTypeRef(T->getExceptionType(I), Record); - Code = pch::TYPE_FUNCTION_PROTO; -} - -void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - Code = pch::TYPE_UNRESOLVED_USING; -} - -void PCHTypeWriter::VisitTypedefType(const TypedefType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - assert(!T->isCanonicalUnqualified() && "Invalid typedef ?"); - Writer.AddTypeRef(T->getCanonicalTypeInternal(), Record); - Code = pch::TYPE_TYPEDEF; -} - -void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) { - Writer.AddStmt(T->getUnderlyingExpr()); - Code = pch::TYPE_TYPEOF_EXPR; -} - -void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) { - Writer.AddTypeRef(T->getUnderlyingType(), Record); - Code = pch::TYPE_TYPEOF; -} - -void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) { - Writer.AddStmt(T->getUnderlyingExpr()); - Code = pch::TYPE_DECLTYPE; -} - -void PCHTypeWriter::VisitTagType(const TagType *T) { - Record.push_back(T->isDependentType()); - Writer.AddDeclRef(T->getDecl(), Record); - assert(!T->isBeingDefined() && - "Cannot serialize in the middle of a type definition"); -} - -void PCHTypeWriter::VisitRecordType(const RecordType *T) { - VisitTagType(T); - Code = pch::TYPE_RECORD; -} - -void PCHTypeWriter::VisitEnumType(const EnumType *T) { - VisitTagType(T); - Code = pch::TYPE_ENUM; -} - -void -PCHTypeWriter::VisitSubstTemplateTypeParmType( - const SubstTemplateTypeParmType *T) { - Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record); - Writer.AddTypeRef(T->getReplacementType(), Record); - Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM; -} - -void -PCHTypeWriter::VisitTemplateSpecializationType( - const TemplateSpecializationType *T) { - Record.push_back(T->isDependentType()); - Writer.AddTemplateName(T->getTemplateName(), Record); - Record.push_back(T->getNumArgs()); - for (TemplateSpecializationType::iterator ArgI = T->begin(), ArgE = T->end(); - ArgI != ArgE; ++ArgI) - Writer.AddTemplateArgument(*ArgI, Record); - Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType() - : T->getCanonicalTypeInternal(), - Record); - Code = pch::TYPE_TEMPLATE_SPECIALIZATION; -} - -void -PCHTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) { - VisitArrayType(T); - Writer.AddStmt(T->getSizeExpr()); - Writer.AddSourceRange(T->getBracketsRange(), Record); - Code = pch::TYPE_DEPENDENT_SIZED_ARRAY; -} - -void -PCHTypeWriter::VisitDependentSizedExtVectorType( - const DependentSizedExtVectorType *T) { - // FIXME: Serialize this type (C++ only) - assert(false && "Cannot serialize dependent sized extended vector types"); -} - -void -PCHTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { - Record.push_back(T->getDepth()); - Record.push_back(T->getIndex()); - Record.push_back(T->isParameterPack()); - Writer.AddIdentifierRef(T->getName(), Record); - Code = pch::TYPE_TEMPLATE_TYPE_PARM; -} - -void -PCHTypeWriter::VisitDependentNameType(const DependentNameType *T) { - Record.push_back(T->getKeyword()); - Writer.AddNestedNameSpecifier(T->getQualifier(), Record); - Writer.AddIdentifierRef(T->getIdentifier(), Record); - Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType() - : T->getCanonicalTypeInternal(), - Record); - Code = pch::TYPE_DEPENDENT_NAME; -} - -void -PCHTypeWriter::VisitDependentTemplateSpecializationType( - const DependentTemplateSpecializationType *T) { - Record.push_back(T->getKeyword()); - Writer.AddNestedNameSpecifier(T->getQualifier(), Record); - Writer.AddIdentifierRef(T->getIdentifier(), Record); - Record.push_back(T->getNumArgs()); - for (DependentTemplateSpecializationType::iterator - I = T->begin(), E = T->end(); I != E; ++I) - Writer.AddTemplateArgument(*I, Record); - Code = pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION; -} - -void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) { - Record.push_back(T->getKeyword()); - Writer.AddNestedNameSpecifier(T->getQualifier(), Record); - Writer.AddTypeRef(T->getNamedType(), Record); - Code = pch::TYPE_ELABORATED; -} - -void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - Writer.AddTypeRef(T->getInjectedSpecializationType(), Record); - Code = pch::TYPE_INJECTED_CLASS_NAME; -} - -void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { - Writer.AddDeclRef(T->getDecl(), Record); - Code = pch::TYPE_OBJC_INTERFACE; -} - -void PCHTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { - Writer.AddTypeRef(T->getBaseType(), Record); - Record.push_back(T->getNumProtocols()); - for (ObjCObjectType::qual_iterator I = T->qual_begin(), - E = T->qual_end(); I != E; ++I) - Writer.AddDeclRef(*I, Record); - Code = pch::TYPE_OBJC_OBJECT; -} - -void -PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Code = pch::TYPE_OBJC_OBJECT_POINTER; -} - -namespace { - -class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { - PCHWriter &Writer; - PCHWriter::RecordData &Record; - -public: - TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) - : Writer(Writer), Record(Record) { } - -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); -#include "clang/AST/TypeLocNodes.def" - - void VisitArrayTypeLoc(ArrayTypeLoc TyLoc); - void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc); -}; - -} - -void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { - // nothing to do -} -void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - Writer.AddSourceLocation(TL.getBuiltinLoc(), Record); - if (TL.needsExtraLocalData()) { - Record.push_back(TL.getWrittenTypeSpec()); - Record.push_back(TL.getWrittenSignSpec()); - Record.push_back(TL.getWrittenWidthSpec()); - Record.push_back(TL.hasModeAttr()); - } -} -void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getStarLoc(), Record); -} -void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getCaretLoc(), Record); -} -void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { - Writer.AddSourceLocation(TL.getAmpLoc(), Record); -} -void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { - Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record); -} -void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getStarLoc(), Record); -} -void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { - Writer.AddSourceLocation(TL.getLBracketLoc(), Record); - Writer.AddSourceLocation(TL.getRBracketLoc(), Record); - Record.push_back(TL.getSizeExpr() ? 1 : 0); - if (TL.getSizeExpr()) - Writer.AddStmt(TL.getSizeExpr()); -} -void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitDependentSizedArrayTypeLoc( - DependentSizedArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( - DependentSizedExtVectorTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - Writer.AddSourceLocation(TL.getLParenLoc(), Record); - Writer.AddSourceLocation(TL.getRParenLoc(), Record); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - Writer.AddDeclRef(TL.getArg(i), Record); -} -void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - Writer.AddSourceLocation(TL.getTypeofLoc(), Record); - Writer.AddSourceLocation(TL.getLParenLoc(), Record); - Writer.AddSourceLocation(TL.getRParenLoc(), Record); -} -void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - Writer.AddSourceLocation(TL.getTypeofLoc(), Record); - Writer.AddSourceLocation(TL.getLParenLoc(), Record); - Writer.AddSourceLocation(TL.getRParenLoc(), Record); - Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record); -} -void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc( - SubstTemplateTypeParmTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitTemplateSpecializationTypeLoc( - TemplateSpecializationTypeLoc TL) { - Writer.AddSourceLocation(TL.getTemplateNameLoc(), Record); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(), - TL.getArgLoc(i).getLocInfo(), Record); -} -void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); -} -void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL) { - Writer.AddSourceLocation(TL.getKeywordLoc(), Record); - Writer.AddSourceRange(TL.getQualifierRange(), Record); - Writer.AddSourceLocation(TL.getNameLoc(), Record); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(), - TL.getArgLoc(I).getLocInfo(), Record); -} -void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { - Record.push_back(TL.hasBaseTypeAsWritten()); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - Writer.AddSourceLocation(TL.getProtocolLoc(i), Record); -} -void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getStarLoc(), Record); -} - -//===----------------------------------------------------------------------===// -// PCHWriter Implementation -//===----------------------------------------------------------------------===// - -static void EmitBlockID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - PCHWriter::RecordData &Record) { - Record.clear(); - Record.push_back(ID); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); - - // Emit the block name if present. - if (Name == 0 || Name[0] == 0) return; - Record.clear(); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); -} - -static void EmitRecordID(unsigned ID, const char *Name, - llvm::BitstreamWriter &Stream, - PCHWriter::RecordData &Record) { - Record.clear(); - Record.push_back(ID); - while (*Name) - Record.push_back(*Name++); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); -} - -static void AddStmtsExprs(llvm::BitstreamWriter &Stream, - PCHWriter::RecordData &Record) { -#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record) - RECORD(STMT_STOP); - RECORD(STMT_NULL_PTR); - RECORD(STMT_NULL); - RECORD(STMT_COMPOUND); - RECORD(STMT_CASE); - RECORD(STMT_DEFAULT); - RECORD(STMT_LABEL); - RECORD(STMT_IF); - RECORD(STMT_SWITCH); - RECORD(STMT_WHILE); - RECORD(STMT_DO); - RECORD(STMT_FOR); - RECORD(STMT_GOTO); - RECORD(STMT_INDIRECT_GOTO); - RECORD(STMT_CONTINUE); - RECORD(STMT_BREAK); - RECORD(STMT_RETURN); - RECORD(STMT_DECL); - RECORD(STMT_ASM); - RECORD(EXPR_PREDEFINED); - RECORD(EXPR_DECL_REF); - RECORD(EXPR_INTEGER_LITERAL); - RECORD(EXPR_FLOATING_LITERAL); - RECORD(EXPR_IMAGINARY_LITERAL); - RECORD(EXPR_STRING_LITERAL); - RECORD(EXPR_CHARACTER_LITERAL); - RECORD(EXPR_PAREN); - RECORD(EXPR_UNARY_OPERATOR); - RECORD(EXPR_SIZEOF_ALIGN_OF); - RECORD(EXPR_ARRAY_SUBSCRIPT); - RECORD(EXPR_CALL); - RECORD(EXPR_MEMBER); - RECORD(EXPR_BINARY_OPERATOR); - RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR); - RECORD(EXPR_CONDITIONAL_OPERATOR); - RECORD(EXPR_IMPLICIT_CAST); - RECORD(EXPR_CSTYLE_CAST); - RECORD(EXPR_COMPOUND_LITERAL); - RECORD(EXPR_EXT_VECTOR_ELEMENT); - RECORD(EXPR_INIT_LIST); - RECORD(EXPR_DESIGNATED_INIT); - RECORD(EXPR_IMPLICIT_VALUE_INIT); - RECORD(EXPR_VA_ARG); - RECORD(EXPR_ADDR_LABEL); - RECORD(EXPR_STMT); - RECORD(EXPR_TYPES_COMPATIBLE); - RECORD(EXPR_CHOOSE); - RECORD(EXPR_GNU_NULL); - RECORD(EXPR_SHUFFLE_VECTOR); - RECORD(EXPR_BLOCK); - RECORD(EXPR_BLOCK_DECL_REF); - RECORD(EXPR_OBJC_STRING_LITERAL); - RECORD(EXPR_OBJC_ENCODE); - RECORD(EXPR_OBJC_SELECTOR_EXPR); - RECORD(EXPR_OBJC_PROTOCOL_EXPR); - RECORD(EXPR_OBJC_IVAR_REF_EXPR); - RECORD(EXPR_OBJC_PROPERTY_REF_EXPR); - RECORD(EXPR_OBJC_KVC_REF_EXPR); - RECORD(EXPR_OBJC_MESSAGE_EXPR); - RECORD(EXPR_OBJC_SUPER_EXPR); - RECORD(STMT_OBJC_FOR_COLLECTION); - RECORD(STMT_OBJC_CATCH); - RECORD(STMT_OBJC_FINALLY); - RECORD(STMT_OBJC_AT_TRY); - RECORD(STMT_OBJC_AT_SYNCHRONIZED); - RECORD(STMT_OBJC_AT_THROW); - RECORD(EXPR_CXX_OPERATOR_CALL); - RECORD(EXPR_CXX_CONSTRUCT); - RECORD(EXPR_CXX_STATIC_CAST); - RECORD(EXPR_CXX_DYNAMIC_CAST); - RECORD(EXPR_CXX_REINTERPRET_CAST); - RECORD(EXPR_CXX_CONST_CAST); - RECORD(EXPR_CXX_FUNCTIONAL_CAST); - RECORD(EXPR_CXX_BOOL_LITERAL); - RECORD(EXPR_CXX_NULL_PTR_LITERAL); -#undef RECORD -} - -void PCHWriter::WriteBlockInfoBlock() { - RecordData Record; - Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); - -#define BLOCK(X) EmitBlockID(pch::X ## _ID, #X, Stream, Record) -#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record) - - // PCH Top-Level Block. - BLOCK(PCH_BLOCK); - RECORD(ORIGINAL_FILE_NAME); - RECORD(TYPE_OFFSET); - RECORD(DECL_OFFSET); - RECORD(LANGUAGE_OPTIONS); - RECORD(METADATA); - RECORD(IDENTIFIER_OFFSET); - RECORD(IDENTIFIER_TABLE); - RECORD(EXTERNAL_DEFINITIONS); - RECORD(SPECIAL_TYPES); - RECORD(STATISTICS); - RECORD(TENTATIVE_DEFINITIONS); - RECORD(UNUSED_FILESCOPED_DECLS); - RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS); - RECORD(SELECTOR_OFFSETS); - RECORD(METHOD_POOL); - RECORD(PP_COUNTER_VALUE); - RECORD(SOURCE_LOCATION_OFFSETS); - RECORD(SOURCE_LOCATION_PRELOADS); - RECORD(STAT_CACHE); - RECORD(EXT_VECTOR_DECLS); - RECORD(VERSION_CONTROL_BRANCH_REVISION); - RECORD(MACRO_DEFINITION_OFFSETS); - RECORD(CHAINED_METADATA); - RECORD(REFERENCED_SELECTOR_POOL); - - // SourceManager Block. - BLOCK(SOURCE_MANAGER_BLOCK); - RECORD(SM_SLOC_FILE_ENTRY); - RECORD(SM_SLOC_BUFFER_ENTRY); - RECORD(SM_SLOC_BUFFER_BLOB); - RECORD(SM_SLOC_INSTANTIATION_ENTRY); - RECORD(SM_LINE_TABLE); - - // Preprocessor Block. - BLOCK(PREPROCESSOR_BLOCK); - RECORD(PP_MACRO_OBJECT_LIKE); - RECORD(PP_MACRO_FUNCTION_LIKE); - RECORD(PP_TOKEN); - RECORD(PP_MACRO_INSTANTIATION); - RECORD(PP_MACRO_DEFINITION); - - // Decls and Types block. - BLOCK(DECLTYPES_BLOCK); - RECORD(TYPE_EXT_QUAL); - RECORD(TYPE_COMPLEX); - RECORD(TYPE_POINTER); - RECORD(TYPE_BLOCK_POINTER); - RECORD(TYPE_LVALUE_REFERENCE); - RECORD(TYPE_RVALUE_REFERENCE); - RECORD(TYPE_MEMBER_POINTER); - RECORD(TYPE_CONSTANT_ARRAY); - RECORD(TYPE_INCOMPLETE_ARRAY); - RECORD(TYPE_VARIABLE_ARRAY); - RECORD(TYPE_VECTOR); - RECORD(TYPE_EXT_VECTOR); - RECORD(TYPE_FUNCTION_PROTO); - RECORD(TYPE_FUNCTION_NO_PROTO); - RECORD(TYPE_TYPEDEF); - RECORD(TYPE_TYPEOF_EXPR); - RECORD(TYPE_TYPEOF); - RECORD(TYPE_RECORD); - RECORD(TYPE_ENUM); - RECORD(TYPE_OBJC_INTERFACE); - RECORD(TYPE_OBJC_OBJECT); - RECORD(TYPE_OBJC_OBJECT_POINTER); - RECORD(DECL_ATTR); - RECORD(DECL_TRANSLATION_UNIT); - RECORD(DECL_TYPEDEF); - RECORD(DECL_ENUM); - RECORD(DECL_RECORD); - RECORD(DECL_ENUM_CONSTANT); - RECORD(DECL_FUNCTION); - RECORD(DECL_OBJC_METHOD); - RECORD(DECL_OBJC_INTERFACE); - RECORD(DECL_OBJC_PROTOCOL); - RECORD(DECL_OBJC_IVAR); - RECORD(DECL_OBJC_AT_DEFS_FIELD); - RECORD(DECL_OBJC_CLASS); - RECORD(DECL_OBJC_FORWARD_PROTOCOL); - RECORD(DECL_OBJC_CATEGORY); - RECORD(DECL_OBJC_CATEGORY_IMPL); - RECORD(DECL_OBJC_IMPLEMENTATION); - RECORD(DECL_OBJC_COMPATIBLE_ALIAS); - RECORD(DECL_OBJC_PROPERTY); - RECORD(DECL_OBJC_PROPERTY_IMPL); - RECORD(DECL_FIELD); - RECORD(DECL_VAR); - RECORD(DECL_IMPLICIT_PARAM); - RECORD(DECL_PARM_VAR); - RECORD(DECL_FILE_SCOPE_ASM); - RECORD(DECL_BLOCK); - RECORD(DECL_CONTEXT_LEXICAL); - RECORD(DECL_CONTEXT_VISIBLE); - // Statements and Exprs can occur in the Decls and Types block. - AddStmtsExprs(Stream, Record); -#undef RECORD -#undef BLOCK - Stream.ExitBlock(); -} - -/// \brief Adjusts the given filename to only write out the portion of the -/// filename that is not part of the system root directory. -/// -/// \param Filename the file name to adjust. -/// -/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and -/// the returned filename will be adjusted by this system root. -/// -/// \returns either the original filename (if it needs no adjustment) or the -/// adjusted filename (which points into the @p Filename parameter). -static const char * -adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) { - assert(Filename && "No file name to adjust?"); - - if (!isysroot) - return Filename; - - // Verify that the filename and the system root have the same prefix. - unsigned Pos = 0; - for (; Filename[Pos] && isysroot[Pos]; ++Pos) - if (Filename[Pos] != isysroot[Pos]) - return Filename; // Prefixes don't match. - - // We hit the end of the filename before we hit the end of the system root. - if (!Filename[Pos]) - return Filename; - - // If the file name has a '/' at the current position, skip over the '/'. - // We distinguish sysroot-based includes from absolute includes by the - // absence of '/' at the beginning of sysroot-based includes. - if (Filename[Pos] == '/') - ++Pos; - - return Filename + Pos; -} - -/// \brief Write the PCH metadata (e.g., i686-apple-darwin9). -void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) { - using namespace llvm; - - // Metadata - const TargetInfo &Target = Context.Target; - BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev(); - MetaAbbrev->Add(BitCodeAbbrevOp( - Chain ? pch::CHAINED_METADATA : pch::METADATA)); - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable - // Target triple or chained PCH name - MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); - - RecordData Record; - Record.push_back(Chain ? pch::CHAINED_METADATA : pch::METADATA); - Record.push_back(pch::VERSION_MAJOR); - Record.push_back(pch::VERSION_MINOR); - Record.push_back(CLANG_VERSION_MAJOR); - Record.push_back(CLANG_VERSION_MINOR); - Record.push_back(isysroot != 0); - // FIXME: This writes the absolute path for chained headers. - const std::string &BlobStr = Chain ? Chain->getFileName() : Target.getTriple().getTriple(); - Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, BlobStr); - - // Original file name - SourceManager &SM = Context.getSourceManager(); - if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev(); - FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME)); - FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); - - llvm::sys::Path MainFilePath(MainFile->getName()); - - MainFilePath.makeAbsolute(); - - const char *MainFileNameStr = MainFilePath.c_str(); - MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, - isysroot); - RecordData Record; - Record.push_back(pch::ORIGINAL_FILE_NAME); - Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); - } - - // Repository branch/version information. - BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev(); - RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION)); - RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag - unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev); - Record.clear(); - Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION); - Stream.EmitRecordWithBlob(RepoAbbrevCode, Record, - getClangFullRepositoryVersion()); -} - -/// \brief Write the LangOptions structure. -void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { - RecordData Record; - Record.push_back(LangOpts.Trigraphs); - Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments. - Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers. - Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode. - Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc) - Record.push_back(LangOpts.GNUKeywords); // Allow GNU-extension keywords - Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'. - Record.push_back(LangOpts.Digraphs); // C94, C99 and C++ - Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants. - Record.push_back(LangOpts.C99); // C99 Support - Record.push_back(LangOpts.Microsoft); // Microsoft extensions. - Record.push_back(LangOpts.CPlusPlus); // C++ Support - Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support - Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords. - - Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled. - Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled. - Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C - // modern abi enabled. - Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced - // modern abi enabled. - Record.push_back(LangOpts.NoConstantCFStrings); // non cfstring generation enabled.. - - Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings - Record.push_back(LangOpts.WritableStrings); // Allow writable strings - Record.push_back(LangOpts.LaxVectorConversions); - Record.push_back(LangOpts.AltiVec); - Record.push_back(LangOpts.Exceptions); // Support exception handling. - Record.push_back(LangOpts.SjLjExceptions); - - Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime. - Record.push_back(LangOpts.Freestanding); // Freestanding implementation - Record.push_back(LangOpts.NoBuiltin); // Do not use builtin functions (-fno-builtin) - - // Whether static initializers are protected by locks. - Record.push_back(LangOpts.ThreadsafeStatics); - Record.push_back(LangOpts.POSIXThreads); - Record.push_back(LangOpts.Blocks); // block extension to C - Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if - // they are unused. - Record.push_back(LangOpts.MathErrno); // Math functions must respect errno - // (modulo the platform support). - - Record.push_back(LangOpts.getSignedOverflowBehavior()); - Record.push_back(LangOpts.HeinousExtensions); - - Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined. - Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be - // defined. - Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as - // opposed to __DYNAMIC__). - Record.push_back(LangOpts.PICLevel); // The value for __PIC__, if non-zero. - - Record.push_back(LangOpts.GNUInline); // Should GNU inline semantics be - // used (instead of C99 semantics). - Record.push_back(LangOpts.NoInline); // Should __NO_INLINE__ be defined. - Record.push_back(LangOpts.AccessControl); // Whether C++ access control should - // be enabled. - Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or - // unsigned type - Record.push_back(LangOpts.ShortWChar); // force wchar_t to be unsigned short - Record.push_back(LangOpts.getGCMode()); - Record.push_back(LangOpts.getVisibilityMode()); - Record.push_back(LangOpts.getStackProtectorMode()); - Record.push_back(LangOpts.InstantiationDepth); - Record.push_back(LangOpts.OpenCL); - Record.push_back(LangOpts.CatchUndefined); - Record.push_back(LangOpts.ElideConstructors); - Record.push_back(LangOpts.SpellChecking); - Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record); -} - -//===----------------------------------------------------------------------===// -// stat cache Serialization -//===----------------------------------------------------------------------===// - -namespace { -// Trait used for the on-disk hash table of stat cache results. -class PCHStatCacheTrait { -public: - typedef const char * key_type; - typedef key_type key_type_ref; - - typedef std::pair<int, struct stat> data_type; - typedef const data_type& data_type_ref; - - static unsigned ComputeHash(const char *path) { - return llvm::HashString(path); - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const char *path, - data_type_ref Data) { - unsigned StrLen = strlen(path); - clang::io::Emit16(Out, StrLen); - unsigned DataLen = 1; // result value - if (Data.first == 0) - DataLen += 4 + 4 + 2 + 8 + 8; - clang::io::Emit8(Out, DataLen); - return std::make_pair(StrLen + 1, DataLen); - } - - void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) { - Out.write(path, KeyLen); - } - - void EmitData(llvm::raw_ostream& Out, key_type_ref, - data_type_ref Data, unsigned DataLen) { - using namespace clang::io; - uint64_t Start = Out.tell(); (void)Start; - - // Result of stat() - Emit8(Out, Data.first? 1 : 0); - - if (Data.first == 0) { - Emit32(Out, (uint32_t) Data.second.st_ino); - Emit32(Out, (uint32_t) Data.second.st_dev); - Emit16(Out, (uint16_t) Data.second.st_mode); - Emit64(Out, (uint64_t) Data.second.st_mtime); - Emit64(Out, (uint64_t) Data.second.st_size); - } - - assert(Out.tell() - Start == DataLen && "Wrong data length"); - } -}; -} // end anonymous namespace - -/// \brief Write the stat() system call cache to the PCH file. -void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { - // Build the on-disk hash table containing information about every - // stat() call. - OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator; - unsigned NumStatEntries = 0; - for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), - StatEnd = StatCalls.end(); - Stat != StatEnd; ++Stat, ++NumStatEntries) { - const char *Filename = Stat->first(); - Generator.insert(Filename, Stat->second); - } - - // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> StatCacheData; - uint32_t BucketOffset; - { - llvm::raw_svector_ostream Out(StatCacheData); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out); - } - - // Create a blob abbreviation - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::STAT_CACHE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned StatCacheAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the stat cache - RecordData Record; - Record.push_back(pch::STAT_CACHE); - Record.push_back(BucketOffset); - Record.push_back(NumStatEntries); - Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str()); -} - -//===----------------------------------------------------------------------===// -// Source Manager Serialization -//===----------------------------------------------------------------------===// - -/// \brief Create an abbreviation for the SLocEntry that refers to a -/// file. -static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives - // FileEntry fields. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time - // HeaderFileInfo fields. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isImport - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // DirInfo - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumIncludes - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // ControllingMacro - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Create an abbreviation for the SLocEntry that refers to a -/// buffer. -static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Create an abbreviation for the SLocEntry that refers to a -/// buffer's blob. -static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Create an abbreviation for the SLocEntry that refers to an -/// buffer. -static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length - return Stream.EmitAbbrev(Abbrev); -} - -/// \brief Writes the block containing the serialized form of the -/// source manager. -/// -/// TODO: We should probably use an on-disk hash table (stored in a -/// blob), indexed based on the file name, so that we only create -/// entries for files that we actually need. In the common case (no -/// errors), we probably won't have to create file entries for any of -/// the files in the AST. -void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, - const Preprocessor &PP, - const char *isysroot) { - RecordData Record; - - // Enter the source manager block. - Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3); - - // Abbreviations for the various kinds of source-location entries. - unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream); - unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream); - unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream); - unsigned SLocInstantiationAbbrv = CreateSLocInstantiationAbbrev(Stream); - - // Write the line table. - if (SourceMgr.hasLineTable()) { - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - // Emit the file names - Record.push_back(LineTable.getNumFilenames()); - for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { - // Emit the file name - const char *Filename = LineTable.getFilename(I); - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - unsigned FilenameLen = Filename? strlen(Filename) : 0; - Record.push_back(FilenameLen); - if (FilenameLen) - Record.insert(Record.end(), Filename, Filename + FilenameLen); - } - - // Emit the line entries - for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); - L != LEnd; ++L) { - // Emit the file ID - Record.push_back(L->first); - - // Emit the line entries - Record.push_back(L->second.size()); - for (std::vector<LineEntry>::iterator LE = L->second.begin(), - LEEnd = L->second.end(); - LE != LEEnd; ++LE) { - Record.push_back(LE->FileOffset); - Record.push_back(LE->LineNo); - Record.push_back(LE->FilenameID); - Record.push_back((unsigned)LE->FileKind); - Record.push_back(LE->IncludeOffset); - } - } - Stream.EmitRecord(pch::SM_LINE_TABLE, Record); - } - - // Write out the source location entry table. We skip the first - // entry, which is always the same dummy entry. - std::vector<uint32_t> SLocEntryOffsets; - RecordData PreloadSLocs; - unsigned BaseSLocID = Chain ? Chain->getTotalNumSLocs() : 0; - SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1 - BaseSLocID); - for (unsigned I = BaseSLocID + 1, N = SourceMgr.sloc_entry_size(); - I != N; ++I) { - // Get this source location entry. - const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I); - - // Record the offset of this source-location entry. - SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); - - // Figure out which record code to use. - unsigned Code; - if (SLoc->isFile()) { - if (SLoc->getFile().getContentCache()->Entry) - Code = pch::SM_SLOC_FILE_ENTRY; - else - Code = pch::SM_SLOC_BUFFER_ENTRY; - } else - Code = pch::SM_SLOC_INSTANTIATION_ENTRY; - Record.clear(); - Record.push_back(Code); - - Record.push_back(SLoc->getOffset()); - if (SLoc->isFile()) { - const SrcMgr::FileInfo &File = SLoc->getFile(); - Record.push_back(File.getIncludeLoc().getRawEncoding()); - Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding - Record.push_back(File.hasLineDirectives()); - - const SrcMgr::ContentCache *Content = File.getContentCache(); - if (Content->Entry) { - // The source location entry is a file. The blob associated - // with this entry is the file name. - - // Emit size/modification time for this file. - Record.push_back(Content->Entry->getSize()); - Record.push_back(Content->Entry->getModificationTime()); - - // Emit header-search information associated with this file. - HeaderFileInfo HFI; - HeaderSearch &HS = PP.getHeaderSearchInfo(); - if (Content->Entry->getUID() < HS.header_file_size()) - HFI = HS.header_file_begin()[Content->Entry->getUID()]; - Record.push_back(HFI.isImport); - Record.push_back(HFI.DirInfo); - Record.push_back(HFI.NumIncludes); - AddIdentifierRef(HFI.ControllingMacro, Record); - - // Turn the file name into an absolute path, if it isn't already. - const char *Filename = Content->Entry->getName(); - llvm::sys::Path FilePath(Filename, strlen(Filename)); - FilePath.makeAbsolute(); - Filename = FilePath.c_str(); - - Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); - Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename); - - // FIXME: For now, preload all file source locations, so that - // we get the appropriate File entries in the reader. This is - // a temporary measure. - PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size()); - } else { - // The source location entry is a buffer. The blob associated - // with this entry contains the contents of the buffer. - - // We add one to the size so that we capture the trailing NULL - // that is required by llvm::MemoryBuffer::getMemBuffer (on - // the reader side). - const llvm::MemoryBuffer *Buffer - = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); - const char *Name = Buffer->getBufferIdentifier(); - Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, - llvm::StringRef(Name, strlen(Name) + 1)); - Record.clear(); - Record.push_back(pch::SM_SLOC_BUFFER_BLOB); - Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, - llvm::StringRef(Buffer->getBufferStart(), - Buffer->getBufferSize() + 1)); - - if (strcmp(Name, "<built-in>") == 0) - PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size()); - } - } else { - // The source location entry is an instantiation. - const SrcMgr::InstantiationInfo &Inst = SLoc->getInstantiation(); - Record.push_back(Inst.getSpellingLoc().getRawEncoding()); - Record.push_back(Inst.getInstantiationLocStart().getRawEncoding()); - Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding()); - - // Compute the token length for this macro expansion. - unsigned NextOffset = SourceMgr.getNextOffset(); - if (I + 1 != N) - NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset(); - Record.push_back(NextOffset - SLoc->getOffset() - 1); - Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record); - } - } - - Stream.ExitBlock(); - - if (SLocEntryOffsets.empty()) - return; - - // Write the source-location offsets table into the PCH block. This - // table is used for lazily loading source-location information. - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SOURCE_LOCATION_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets - unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); - - Record.clear(); - Record.push_back(pch::SOURCE_LOCATION_OFFSETS); - Record.push_back(SLocEntryOffsets.size()); - Record.push_back(SourceMgr.getNextOffset()); - Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, - (const char *)data(SLocEntryOffsets), - SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0])); - - // Write the source location entry preloads array, telling the PCH - // reader which source locations entries it should load eagerly. - Stream.EmitRecord(pch::SOURCE_LOCATION_PRELOADS, PreloadSLocs); -} - -//===----------------------------------------------------------------------===// -// Preprocessor Serialization -//===----------------------------------------------------------------------===// - -/// \brief Writes the block containing the serialized form of the -/// preprocessor. -/// -void PCHWriter::WritePreprocessor(const Preprocessor &PP) { - RecordData Record; - - // If the preprocessor __COUNTER__ value has been bumped, remember it. - if (PP.getCounterValue() != 0) { - Record.push_back(PP.getCounterValue()); - Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record); - Record.clear(); - } - - // Enter the preprocessor block. - Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2); - - // If the PCH file contains __DATE__ or __TIME__ emit a warning about this. - // FIXME: use diagnostics subsystem for localization etc. - if (PP.SawDateOrTime()) - fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n"); - - // Loop over all the macro definitions that are live at the end of the file, - // emitting each to the PP section. - PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); - for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); - I != E; ++I) { - // FIXME: This emits macros in hash table order, we should do it in a stable - // order so that output is reproducible. - MacroInfo *MI = I->second; - - // Don't emit builtin macros like __LINE__ to the PCH file unless they have - // been redefined by the header (in which case they are not isBuiltinMacro). - // Also skip macros from a PCH file if we're chaining. - if (MI->isBuiltinMacro() || (Chain && MI->isFromPCH())) - continue; - - AddIdentifierRef(I->first, Record); - MacroOffsets[I->first] = Stream.GetCurrentBitNo(); - Record.push_back(MI->getDefinitionLoc().getRawEncoding()); - Record.push_back(MI->isUsed()); - - unsigned Code; - if (MI->isObjectLike()) { - Code = pch::PP_MACRO_OBJECT_LIKE; - } else { - Code = pch::PP_MACRO_FUNCTION_LIKE; - - Record.push_back(MI->isC99Varargs()); - Record.push_back(MI->isGNUVarargs()); - Record.push_back(MI->getNumArgs()); - for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); - I != E; ++I) - AddIdentifierRef(*I, Record); - } - - // If we have a detailed preprocessing record, record the macro definition - // ID that corresponds to this macro. - if (PPRec) - Record.push_back(getMacroDefinitionID(PPRec->findMacroDefinition(MI))); - - Stream.EmitRecord(Code, Record); - Record.clear(); - - // Emit the tokens array. - for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { - // Note that we know that the preprocessor does not have any annotation - // tokens in it because they are created by the parser, and thus can't be - // in a macro definition. - const Token &Tok = MI->getReplacementToken(TokNo); - - Record.push_back(Tok.getLocation().getRawEncoding()); - Record.push_back(Tok.getLength()); - - // FIXME: When reading literal tokens, reconstruct the literal pointer if - // it is needed. - AddIdentifierRef(Tok.getIdentifierInfo(), Record); - - // FIXME: Should translate token kind to a stable encoding. - Record.push_back(Tok.getKind()); - // FIXME: Should translate token flags to a stable encoding. - Record.push_back(Tok.getFlags()); - - Stream.EmitRecord(pch::PP_TOKEN, Record); - Record.clear(); - } - ++NumMacros; - } - - // If the preprocessor has a preprocessing record, emit it. - unsigned NumPreprocessingRecords = 0; - if (PPRec) { - for (PreprocessingRecord::iterator E = PPRec->begin(), EEnd = PPRec->end(); - E != EEnd; ++E) { - Record.clear(); - - if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) { - Record.push_back(NumPreprocessingRecords++); - AddSourceLocation(MI->getSourceRange().getBegin(), Record); - AddSourceLocation(MI->getSourceRange().getEnd(), Record); - AddIdentifierRef(MI->getName(), Record); - Record.push_back(getMacroDefinitionID(MI->getDefinition())); - Stream.EmitRecord(pch::PP_MACRO_INSTANTIATION, Record); - continue; - } - - if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) { - // Record this macro definition's location. - pch::IdentID ID = getMacroDefinitionID(MD); - if (ID != MacroDefinitionOffsets.size()) { - if (ID > MacroDefinitionOffsets.size()) - MacroDefinitionOffsets.resize(ID + 1); - - MacroDefinitionOffsets[ID] = Stream.GetCurrentBitNo(); - } else - MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo()); - - Record.push_back(NumPreprocessingRecords++); - Record.push_back(ID); - AddSourceLocation(MD->getSourceRange().getBegin(), Record); - AddSourceLocation(MD->getSourceRange().getEnd(), Record); - AddIdentifierRef(MD->getName(), Record); - AddSourceLocation(MD->getLocation(), Record); - Stream.EmitRecord(pch::PP_MACRO_DEFINITION, Record); - continue; - } - } - } - - Stream.ExitBlock(); - - // Write the offsets table for the preprocessing record. - if (NumPreprocessingRecords > 0) { - // Write the offsets table for identifier IDs. - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::MACRO_DEFINITION_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of records - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macro defs - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MacroDefOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - - Record.clear(); - Record.push_back(pch::MACRO_DEFINITION_OFFSETS); - Record.push_back(NumPreprocessingRecords); - Record.push_back(MacroDefinitionOffsets.size()); - Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record, - (const char *)data(MacroDefinitionOffsets), - MacroDefinitionOffsets.size() * sizeof(uint32_t)); - } -} - -//===----------------------------------------------------------------------===// -// Type Serialization -//===----------------------------------------------------------------------===// - -/// \brief Write the representation of a type to the PCH stream. -void PCHWriter::WriteType(QualType T) { - pch::TypeID &ID = TypeIDs[T]; - if (ID == 0) // we haven't seen this type before. - ID = NextTypeID++; - - // Record the offset for this type. - unsigned Index = ID - FirstTypeID; - if (TypeOffsets.size() == Index) - TypeOffsets.push_back(Stream.GetCurrentBitNo()); - else if (TypeOffsets.size() < Index) { - TypeOffsets.resize(Index + 1); - TypeOffsets[Index] = Stream.GetCurrentBitNo(); - } - - RecordData Record; - - // Emit the type's representation. - PCHTypeWriter W(*this, Record); - - if (T.hasLocalNonFastQualifiers()) { - Qualifiers Qs = T.getLocalQualifiers(); - AddTypeRef(T.getLocalUnqualifiedType(), Record); - Record.push_back(Qs.getAsOpaqueValue()); - W.Code = pch::TYPE_EXT_QUAL; - } else { - switch (T->getTypeClass()) { - // For all of the concrete, non-dependent types, call the - // appropriate visitor function. -#define TYPE(Class, Base) \ - case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break; -#define ABSTRACT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - } - } - - // Emit the serialized record. - Stream.EmitRecord(W.Code, Record); - - // Flush any expressions that were written as part of this type. - FlushStmts(); -} - -//===----------------------------------------------------------------------===// -// Declaration Serialization -//===----------------------------------------------------------------------===// - -/// \brief Write the block containing all of the declaration IDs -/// lexically declared within the given DeclContext. -/// -/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the -/// bistream, or 0 if no block was written. -uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context, - DeclContext *DC) { - if (DC->decls_empty()) - return 0; - - uint64_t Offset = Stream.GetCurrentBitNo(); - RecordData Record; - Record.push_back(pch::DECL_CONTEXT_LEXICAL); - llvm::SmallVector<pch::DeclID, 64> Decls; - for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); - D != DEnd; ++D) - Decls.push_back(GetDeclRef(*D)); - - ++NumLexicalDeclContexts; - Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, - reinterpret_cast<char*>(Decls.data()), Decls.size() * sizeof(pch::DeclID)); - return Offset; -} - -/// \brief Write the block containing all of the declaration IDs -/// visible from the given DeclContext. -/// -/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the -/// bistream, or 0 if no block was written. -uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context, - DeclContext *DC) { - if (DC->getPrimaryContext() != DC) - return 0; - - // Since there is no name lookup into functions or methods, don't bother to - // build a visible-declarations table for these entities. - if (DC->isFunctionOrMethod()) - return 0; - - // If not in C++, we perform name lookup for the translation unit via the - // IdentifierInfo chains, don't bother to build a visible-declarations table. - // FIXME: In C++ we need the visible declarations in order to "see" the - // friend declarations, is there a way to do this without writing the table ? - if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus) - return 0; - - // Force the DeclContext to build a its name-lookup table. - DC->lookup(DeclarationName()); - - // Serialize the contents of the mapping used for lookup. Note that, - // although we have two very different code paths, the serialized - // representation is the same for both cases: a declaration name, - // followed by a size, followed by references to the visible - // declarations that have that name. - uint64_t Offset = Stream.GetCurrentBitNo(); - RecordData Record; - StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr()); - if (!Map) - return 0; - - for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end(); - D != DEnd; ++D) { - AddDeclarationName(D->first, Record); - DeclContext::lookup_result Result = D->second.getLookupResult(Context); - Record.push_back(Result.second - Result.first); - for (; Result.first != Result.second; ++Result.first) - AddDeclRef(*Result.first, Record); - } - - if (Record.size() == 0) - return 0; - - Stream.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record); - ++NumVisibleDeclContexts; - return Offset; -} - -void PCHWriter::WriteTypeDeclOffsets() { - using namespace llvm; - RecordData Record; - - // Write the type offsets array - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::TYPE_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block - unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - Record.clear(); - Record.push_back(pch::TYPE_OFFSET); - Record.push_back(TypeOffsets.size()); - Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, - (const char *)data(TypeOffsets), - TypeOffsets.size() * sizeof(TypeOffsets[0])); - - // Write the declaration offsets array - Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block - unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - Record.clear(); - Record.push_back(pch::DECL_OFFSET); - Record.push_back(DeclOffsets.size()); - Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, - (const char *)data(DeclOffsets), - DeclOffsets.size() * sizeof(DeclOffsets[0])); -} - -//===----------------------------------------------------------------------===// -// Global Method Pool and Selector Serialization -//===----------------------------------------------------------------------===// - -namespace { -// Trait used for the on-disk hash table used in the method pool. -class PCHMethodPoolTrait { - PCHWriter &Writer; - -public: - typedef Selector key_type; - typedef key_type key_type_ref; - - struct data_type { - pch::SelectorID ID; - ObjCMethodList Instance, Factory; - }; - typedef const data_type& data_type_ref; - - explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { } - - 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; - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel, - data_type_ref Methods) { - unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); - clang::io::Emit16(Out, KeyLen); - unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts - for (const ObjCMethodList *Method = &Methods.Instance; Method; - Method = Method->Next) - if (Method->Method) - DataLen += 4; - for (const ObjCMethodList *Method = &Methods.Factory; Method; - Method = Method->Next) - if (Method->Method) - DataLen += 4; - clang::io::Emit16(Out, DataLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) { - uint64_t Start = Out.tell(); - assert((Start >> 32) == 0 && "Selector key offset too large"); - Writer.SetSelectorOffset(Sel, Start); - unsigned N = Sel.getNumArgs(); - clang::io::Emit16(Out, N); - if (N == 0) - N = 1; - for (unsigned I = 0; I != N; ++I) - clang::io::Emit32(Out, - Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); - } - - void EmitData(llvm::raw_ostream& Out, key_type_ref, - data_type_ref Methods, unsigned DataLen) { - uint64_t Start = Out.tell(); (void)Start; - clang::io::Emit32(Out, Methods.ID); - unsigned NumInstanceMethods = 0; - for (const ObjCMethodList *Method = &Methods.Instance; Method; - Method = Method->Next) - if (Method->Method) - ++NumInstanceMethods; - - unsigned NumFactoryMethods = 0; - for (const ObjCMethodList *Method = &Methods.Factory; Method; - Method = Method->Next) - if (Method->Method) - ++NumFactoryMethods; - - clang::io::Emit16(Out, NumInstanceMethods); - clang::io::Emit16(Out, NumFactoryMethods); - for (const ObjCMethodList *Method = &Methods.Instance; Method; - Method = Method->Next) - if (Method->Method) - clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); - for (const ObjCMethodList *Method = &Methods.Factory; Method; - Method = Method->Next) - if (Method->Method) - clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); - - assert(Out.tell() - Start == DataLen && "Data length is wrong"); - } -}; -} // end anonymous namespace - -/// \brief Write ObjC data: selectors and the method pool. -/// -/// The method pool contains both instance and factory methods, stored -/// in an on-disk hash table indexed by the selector. The hash table also -/// contains an empty entry for every other selector known to Sema. -void PCHWriter::WriteSelectors(Sema &SemaRef) { - using namespace llvm; - - // Do we have to do anything at all? - if (SemaRef.MethodPool.empty() && SelectorIDs.empty()) - return; - unsigned NumTableEntries = 0; - // Create and write out the blob that contains selectors and the method pool. - { - OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator; - - // Create the on-disk hash table representation. We walk through every - // selector we've seen and look it up in the method pool. - SelectorOffsets.resize(NextSelectorID - FirstSelectorID); - for (llvm::DenseMap<Selector, pch::SelectorID>::iterator - I = SelectorIDs.begin(), E = SelectorIDs.end(); - I != E; ++I) { - Selector S = I->first; - Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S); - PCHMethodPoolTrait::data_type Data = { - I->second, - ObjCMethodList(), - ObjCMethodList() - }; - if (F != SemaRef.MethodPool.end()) { - Data.Instance = F->second.first; - Data.Factory = F->second.second; - } - // Only write this selector if it's not in an existing PCH or something - // changed. - if (Chain && I->second < FirstSelectorID) { - // Selector already exists. Did it change? - bool changed = false; - for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method; - M = M->Next) { - if (M->Method->getPCHLevel() == 0) - changed = true; - } - for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method; - M = M->Next) { - if (M->Method->getPCHLevel() == 0) - changed = true; - } - if (!changed) - continue; - } else if (Data.Instance.Method || Data.Factory.Method) { - // A new method pool entry. - ++NumTableEntries; - } - Generator.insert(S, Data); - } - - // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> MethodPool; - uint32_t BucketOffset; - { - PCHMethodPoolTrait Trait(*this); - llvm::raw_svector_ostream Out(MethodPool); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out, Trait); - } - - // Create a blob abbreviation - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::METHOD_POOL)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned MethodPoolAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the method pool - RecordData Record; - Record.push_back(pch::METHOD_POOL); - Record.push_back(BucketOffset); - Record.push_back(NumTableEntries); - Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str()); - - // Create a blob abbreviation for the selector table offsets. - Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::SELECTOR_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the selector offsets table. - Record.clear(); - Record.push_back(pch::SELECTOR_OFFSETS); - Record.push_back(SelectorOffsets.size()); - Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, - (const char *)data(SelectorOffsets), - SelectorOffsets.size() * 4); - } -} - -/// \brief Write the selectors referenced in @selector expression into PCH file. -void PCHWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { - using namespace llvm; - if (SemaRef.ReferencedSelectors.empty()) - return; - - RecordData Record; - - // Note: this writes out all references even for a dependent PCH. But it is - // very tricky to fix, and given that @selector shouldn't really appear in - // headers, probably not worth it. It's not a correctness issue. - for (DenseMap<Selector, SourceLocation>::iterator S = - SemaRef.ReferencedSelectors.begin(), - E = SemaRef.ReferencedSelectors.end(); S != E; ++S) { - Selector Sel = (*S).first; - SourceLocation Loc = (*S).second; - AddSelectorRef(Sel, Record); - AddSourceLocation(Loc, Record); - } - Stream.EmitRecord(pch::REFERENCED_SELECTOR_POOL, Record); -} - -//===----------------------------------------------------------------------===// -// Identifier Table Serialization -//===----------------------------------------------------------------------===// - -namespace { -class PCHIdentifierTableTrait { - PCHWriter &Writer; - Preprocessor &PP; - - /// \brief Determines whether this is an "interesting" identifier - /// that needs a full IdentifierInfo structure written into the hash - /// table. - static bool isInterestingIdentifier(const IdentifierInfo *II) { - return II->isPoisoned() || - II->isExtensionToken() || - II->hasMacroDefinition() || - II->getObjCOrBuiltinID() || - II->getFETokenInfo<void>(); - } - -public: - typedef const IdentifierInfo* key_type; - typedef key_type key_type_ref; - - typedef pch::IdentID data_type; - typedef data_type data_type_ref; - - PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP) - : Writer(Writer), PP(PP) { } - - static unsigned ComputeHash(const IdentifierInfo* II) { - return llvm::HashString(II->getName()); - } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II, - pch::IdentID ID) { - unsigned KeyLen = II->getLength() + 1; - unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 - if (isInterestingIdentifier(II)) { - DataLen += 2; // 2 bytes for builtin ID, flags - if (II->hasMacroDefinition() && - !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro()) - DataLen += 4; - for (IdentifierResolver::iterator D = IdentifierResolver::begin(II), - DEnd = IdentifierResolver::end(); - D != DEnd; ++D) - DataLen += sizeof(pch::DeclID); - } - clang::io::Emit16(Out, DataLen); - // We emit the key length after the data length so that every - // string is preceded by a 16-bit length. This matches the PTH - // format for storing identifiers. - clang::io::Emit16(Out, KeyLen); - return std::make_pair(KeyLen, DataLen); - } - - void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II, - unsigned KeyLen) { - // Record the location of the key data. This is used when generating - // the mapping from persistent IDs to strings. - Writer.SetIdentifierOffset(II, Out.tell()); - Out.write(II->getNameStart(), KeyLen); - } - - void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II, - pch::IdentID ID, unsigned) { - if (!isInterestingIdentifier(II)) { - clang::io::Emit32(Out, ID << 1); - return; - } - - clang::io::Emit32(Out, (ID << 1) | 0x01); - uint32_t Bits = 0; - bool hasMacroDefinition = - II->hasMacroDefinition() && - !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro(); - Bits = (uint32_t)II->getObjCOrBuiltinID(); - Bits = (Bits << 1) | unsigned(hasMacroDefinition); - Bits = (Bits << 1) | unsigned(II->isExtensionToken()); - Bits = (Bits << 1) | unsigned(II->isPoisoned()); - Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); - Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); - clang::io::Emit16(Out, Bits); - - if (hasMacroDefinition) - clang::io::Emit32(Out, Writer.getMacroOffset(II)); - - // Emit the declaration IDs in reverse order, because the - // IdentifierResolver provides the declarations as they would be - // visible (e.g., the function "stat" would come before the struct - // "stat"), but IdentifierResolver::AddDeclToIdentifierChain() - // adds declarations to the end of the list (so we need to see the - // struct "status" before the function "status"). - // Only emit declarations that aren't from a chained PCH, though. - llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), - IdentifierResolver::end()); - for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(), - DEnd = Decls.rend(); - D != DEnd; ++D) - clang::io::Emit32(Out, Writer.getDeclID(*D)); - } -}; -} // end anonymous namespace - -/// \brief Write the identifier table into the PCH file. -/// -/// The identifier table consists of a blob containing string data -/// (the actual identifiers themselves) and a separate "offsets" index -/// that maps identifier IDs to locations within the blob. -void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { - using namespace llvm; - - // Create and write out the blob that contains the identifier - // strings. - { - OnDiskChainedHashTableGenerator<PCHIdentifierTableTrait> Generator; - - // Look for any identifiers that were named while processing the - // headers, but are otherwise not needed. We add these to the hash - // table to enable checking of the predefines buffer in the case - // where the user adds new macro definitions when building the PCH - // file. - for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(), - IDEnd = PP.getIdentifierTable().end(); - ID != IDEnd; ++ID) - getIdentifierRef(ID->second); - - // Create the on-disk hash table representation. We only store offsets - // for identifiers that appear here for the first time. - IdentifierOffsets.resize(NextIdentID - FirstIdentID); - for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator - ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); - ID != IDEnd; ++ID) { - assert(ID->first && "NULL identifier in identifier table"); - if (!Chain || !ID->first->isFromPCH()) - Generator.insert(ID->first, ID->second); - } - - // Create the on-disk hash table in a buffer. - llvm::SmallString<4096> IdentifierTable; - uint32_t BucketOffset; - { - PCHIdentifierTableTrait Trait(*this, PP); - llvm::raw_svector_ostream Out(IdentifierTable); - // Make sure that no bucket is at offset 0 - clang::io::Emit32(Out, 0); - BucketOffset = Generator.Emit(Out, Trait); - } - - // Create a blob abbreviation - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); - - // Write the identifier table - RecordData Record; - Record.push_back(pch::IDENTIFIER_TABLE); - Record.push_back(BucketOffset); - Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); - } - - // Write the offsets table for identifier IDs. - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_OFFSET)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); - - RecordData Record; - Record.push_back(pch::IDENTIFIER_OFFSET); - Record.push_back(IdentifierOffsets.size()); - Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, - (const char *)data(IdentifierOffsets), - IdentifierOffsets.size() * sizeof(uint32_t)); -} - -//===----------------------------------------------------------------------===// -// General Serialization Routines -//===----------------------------------------------------------------------===// - -/// \brief Write a record containing the given attributes. -void PCHWriter::WriteAttributeRecord(const Attr *Attr) { - RecordData Record; - for (; Attr; Attr = Attr->getNext()) { - Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs - Record.push_back(Attr->isInherited()); - switch (Attr->getKind()) { - default: - assert(0 && "Does not support PCH writing for this attribute yet!"); - break; - case attr::Alias: - AddString(cast<AliasAttr>(Attr)->getAliasee(), Record); - break; - - case attr::AlignMac68k: - break; - - case attr::Aligned: - Record.push_back(cast<AlignedAttr>(Attr)->getAlignment()); - break; - - case attr::AlwaysInline: - break; - - case attr::AnalyzerNoReturn: - break; - - case attr::Annotate: - AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record); - break; - - case attr::AsmLabel: - AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record); - break; - - case attr::BaseCheck: - break; - - case attr::Blocks: - Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable - break; - - case attr::CDecl: - break; - - case attr::Cleanup: - AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record); - break; - - case attr::Const: - break; - - case attr::Constructor: - Record.push_back(cast<ConstructorAttr>(Attr)->getPriority()); - break; - - case attr::DLLExport: - case attr::DLLImport: - case attr::Deprecated: - break; - - case attr::Destructor: - Record.push_back(cast<DestructorAttr>(Attr)->getPriority()); - break; - - case attr::FastCall: - case attr::Final: - break; - - case attr::Format: { - const FormatAttr *Format = cast<FormatAttr>(Attr); - AddString(Format->getType(), Record); - Record.push_back(Format->getFormatIdx()); - Record.push_back(Format->getFirstArg()); - break; - } - - case attr::FormatArg: { - const FormatArgAttr *Format = cast<FormatArgAttr>(Attr); - Record.push_back(Format->getFormatIdx()); - break; - } - - case attr::Sentinel : { - const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr); - Record.push_back(Sentinel->getSentinel()); - Record.push_back(Sentinel->getNullPos()); - break; - } - - case attr::GNUInline: - case attr::Hiding: - case attr::IBAction: - case attr::IBOutlet: - case attr::Malloc: - case attr::NoDebug: - case attr::NoInline: - case attr::NoReturn: - case attr::NoThrow: - break; - - case attr::IBOutletCollection: { - const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr); - AddDeclRef(ICA->getClass(), Record); - break; - } - - case attr::NonNull: { - const NonNullAttr *NonNull = cast<NonNullAttr>(Attr); - Record.push_back(NonNull->size()); - Record.insert(Record.end(), NonNull->begin(), NonNull->end()); - break; - } - - case attr::CFReturnsNotRetained: - case attr::CFReturnsRetained: - case attr::NSReturnsNotRetained: - case attr::NSReturnsRetained: - case attr::ObjCException: - case attr::ObjCNSObject: - case attr::Overloadable: - case attr::Override: - break; - - case attr::MaxFieldAlignment: - Record.push_back(cast<MaxFieldAlignmentAttr>(Attr)->getAlignment()); - break; - - case attr::Packed: - break; - - case attr::Pure: - break; - - case attr::Regparm: - Record.push_back(cast<RegparmAttr>(Attr)->getNumParams()); - break; - - case attr::ReqdWorkGroupSize: - Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim()); - Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim()); - Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim()); - break; - - case attr::Section: - AddString(cast<SectionAttr>(Attr)->getName(), Record); - break; - - case attr::StdCall: - case attr::TransparentUnion: - case attr::Unavailable: - case attr::Unused: - case attr::Used: - break; - - case attr::Visibility: - // FIXME: stable encoding - Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility()); - Record.push_back(cast<VisibilityAttr>(Attr)->isFromPragma()); - break; - - case attr::WarnUnusedResult: - case attr::Weak: - case attr::WeakRef: - case attr::WeakImport: - break; - } - } - - Stream.EmitRecord(pch::DECL_ATTR, Record); -} - -void PCHWriter::AddString(const std::string &Str, RecordData &Record) { - Record.push_back(Str.size()); - Record.insert(Record.end(), Str.begin(), Str.end()); -} - -/// \brief Note that the identifier II occurs at the given offset -/// within the identifier table. -void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { - pch::IdentID ID = IdentifierIDs[II]; - // Only store offsets new to this PCH file. Other identifier names are looked - // up earlier in the chain and thus don't need an offset. - if (ID >= FirstIdentID) - IdentifierOffsets[ID - FirstIdentID] = Offset; -} - -/// \brief Note that the selector Sel occurs at the given offset -/// within the method pool/selector table. -void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { - unsigned ID = SelectorIDs[Sel]; - assert(ID && "Unknown selector"); - // Don't record offsets for selectors that are also available in a different - // file. - if (ID < FirstSelectorID) - return; - SelectorOffsets[ID - FirstSelectorID] = Offset; -} - -PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream) - : Stream(Stream), Chain(0), FirstDeclID(1), NextDeclID(FirstDeclID), - FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), - FirstIdentID(1), NextIdentID(FirstIdentID), FirstSelectorID(1), - NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit), - NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), - NumVisibleDeclContexts(0) { -} - -void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { - // Emit the file header. - Stream.Emit((unsigned)'C', 8); - Stream.Emit((unsigned)'P', 8); - Stream.Emit((unsigned)'C', 8); - Stream.Emit((unsigned)'H', 8); - - WriteBlockInfoBlock(); - - if (Chain) - WritePCHChain(SemaRef, StatCalls, isysroot); - else - WritePCHCore(SemaRef, StatCalls, isysroot); -} - -void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { - using namespace llvm; - - ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - - // The translation unit is the first declaration we'll emit. - DeclIDs[Context.getTranslationUnitDecl()] = 1; - ++NextDeclID; - DeclTypesToEmit.push(Context.getTranslationUnitDecl()); - - // Make sure that we emit IdentifierInfos (and any attached - // declarations) for builtins. - { - IdentifierTable &Table = PP.getIdentifierTable(); - llvm::SmallVector<const char *, 32> BuiltinNames; - Context.BuiltinInfo.GetBuiltinNames(BuiltinNames, - Context.getLangOptions().NoBuiltin); - for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I) - getIdentifierRef(&Table.get(BuiltinNames[I])); - } - - // Build a record containing all of the tentative definitions in this file, in - // TentativeDefinitions order. Generally, this record will be empty for - // headers. - RecordData TentativeDefinitions; - for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) { - AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions); - } - - // Build a record containing all of the file scoped decls in this file. - RecordData UnusedFileScopedDecls; - for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i) - AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls); - - RecordData WeakUndeclaredIdentifiers; - if (!SemaRef.WeakUndeclaredIdentifiers.empty()) { - WeakUndeclaredIdentifiers.push_back( - SemaRef.WeakUndeclaredIdentifiers.size()); - for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator - I = SemaRef.WeakUndeclaredIdentifiers.begin(), - E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) { - AddIdentifierRef(I->first, WeakUndeclaredIdentifiers); - AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers); - WeakUndeclaredIdentifiers.push_back(I->second.getUsed()); - } - } - - // Build a record containing all of the locally-scoped external - // declarations in this header file. Generally, this record will be - // empty. - RecordData LocallyScopedExternalDecls; - // FIXME: This is filling in the PCH file in densemap order which is - // nondeterminstic! - for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator - TD = SemaRef.LocallyScopedExternalDecls.begin(), - TDEnd = SemaRef.LocallyScopedExternalDecls.end(); - TD != TDEnd; ++TD) - AddDeclRef(TD->second, LocallyScopedExternalDecls); - - // Build a record containing all of the ext_vector declarations. - RecordData ExtVectorDecls; - for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) - AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls); - - // Build a record containing all of the VTable uses information. - RecordData VTableUses; - if (!SemaRef.VTableUses.empty()) { - VTableUses.push_back(SemaRef.VTableUses.size()); - for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { - AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); - AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); - VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); - } - } - - // Build a record containing all of dynamic classes declarations. - RecordData DynamicClasses; - for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I) - AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses); - - // Build a record containing all of pending implicit instantiations. - RecordData PendingImplicitInstantiations; - for (std::deque<Sema::PendingImplicitInstantiation>::iterator - I = SemaRef.PendingImplicitInstantiations.begin(), - N = SemaRef.PendingImplicitInstantiations.end(); I != N; ++I) { - AddDeclRef(I->first, PendingImplicitInstantiations); - AddSourceLocation(I->second, PendingImplicitInstantiations); - } - assert(SemaRef.PendingLocalImplicitInstantiations.empty() && - "There are local ones at end of translation unit!"); - - // Build a record containing some declaration references. - RecordData SemaDeclRefs; - if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) { - AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); - } - - // Write the remaining PCH contents. - RecordData Record; - Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5); - WriteMetadata(Context, isysroot); - WriteLanguageOptions(Context.getLangOptions()); - if (StatCalls && !isysroot) - WriteStatCache(*StatCalls); - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); - // Write the record of special types. - Record.clear(); - - AddTypeRef(Context.getBuiltinVaListType(), Record); - AddTypeRef(Context.getObjCIdType(), Record); - AddTypeRef(Context.getObjCSelType(), Record); - AddTypeRef(Context.getObjCProtoType(), Record); - AddTypeRef(Context.getObjCClassType(), Record); - AddTypeRef(Context.getRawCFConstantStringType(), Record); - AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record); - AddTypeRef(Context.getFILEType(), Record); - AddTypeRef(Context.getjmp_bufType(), Record); - AddTypeRef(Context.getsigjmp_bufType(), Record); - AddTypeRef(Context.ObjCIdRedefinitionType, Record); - AddTypeRef(Context.ObjCClassRedefinitionType, Record); - AddTypeRef(Context.getRawBlockdescriptorType(), Record); - AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record); - AddTypeRef(Context.ObjCSelRedefinitionType, Record); - AddTypeRef(Context.getRawNSConstantStringType(), Record); - Record.push_back(Context.isInt128Installed()); - Stream.EmitRecord(pch::SPECIAL_TYPES, Record); - - // Keep writing types and declarations until all types and - // declarations have been written. - Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3); - WriteDeclsBlockAbbrevs(); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - Stream.ExitBlock(); - - WritePreprocessor(PP); - WriteSelectors(SemaRef); - WriteReferencedSelectorsPool(SemaRef); - WriteIdentifierTable(PP); - - WriteTypeDeclOffsets(); - - // Write the record containing external, unnamed definitions. - if (!ExternalDefinitions.empty()) - Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused file scoped decls. - if (!UnusedFileScopedDecls.empty()) - Stream.EmitRecord(pch::UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); - - // Write the record containing weak undeclared identifiers. - if (!WeakUndeclaredIdentifiers.empty()) - Stream.EmitRecord(pch::WEAK_UNDECLARED_IDENTIFIERS, - WeakUndeclaredIdentifiers); - - // Write the record containing locally-scoped external definitions. - if (!LocallyScopedExternalDecls.empty()) - Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS, - LocallyScopedExternalDecls); - - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(pch::VTABLE_USES, VTableUses); - - // Write the record containing dynamic classes declarations. - if (!DynamicClasses.empty()) - Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses); - - // Write the record containing pending implicit instantiations. - if (!PendingImplicitInstantiations.empty()) - Stream.EmitRecord(pch::PENDING_IMPLICIT_INSTANTIATIONS, - PendingImplicitInstantiations); - - // Write the record containing declaration references of Sema. - if (!SemaDeclRefs.empty()) - Stream.EmitRecord(pch::SEMA_DECL_REFS, SemaDeclRefs); - - // Some simple statistics - Record.clear(); - Record.push_back(NumStatements); - Record.push_back(NumMacros); - Record.push_back(NumLexicalDeclContexts); - Record.push_back(NumVisibleDeclContexts); - Stream.EmitRecord(pch::STATISTICS, Record); - Stream.ExitBlock(); -} - -void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { - using namespace llvm; - - FirstDeclID += Chain->getTotalNumDecls(); - FirstTypeID += Chain->getTotalNumTypes(); - FirstIdentID += Chain->getTotalNumIdentifiers(); - FirstSelectorID += Chain->getTotalNumSelectors(); - NextDeclID = FirstDeclID; - NextTypeID = FirstTypeID; - NextIdentID = FirstIdentID; - NextSelectorID = FirstSelectorID; - - ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - - RecordData Record; - Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5); - WriteMetadata(Context, isysroot); - if (StatCalls && !isysroot) - WriteStatCache(*StatCalls); - // FIXME: Source manager block should only write new stuff, which could be - // done by tracking the largest ID in the chain - WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); - - // The special types are in the chained PCH. - - // We don't start with the translation unit, but with its decls that - // don't come from the other PCH. - const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - llvm::SmallVector<pch::DeclID, 64> NewGlobalDecls; - for (DeclContext::decl_iterator I = TU->noload_decls_begin(), - E = TU->noload_decls_end(); - I != E; ++I) { - if ((*I)->getPCHLevel() == 0) - NewGlobalDecls.push_back(GetDeclRef(*I)); - else if ((*I)->isChangedSinceDeserialization()) - (void)GetDeclRef(*I); // Make sure it's written, but don't record it. - } - // We also need to write a lexical updates block for the TU. - llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); - Abv->Add(llvm::BitCodeAbbrevOp(pch::TU_UPDATE_LEXICAL)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(Abv); - Record.clear(); - Record.push_back(pch::TU_UPDATE_LEXICAL); - Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - reinterpret_cast<const char*>(NewGlobalDecls.data()), - NewGlobalDecls.size() * sizeof(pch::DeclID)); - - // Build a record containing all of the new tentative definitions in this - // file, in TentativeDefinitions order. - RecordData TentativeDefinitions; - for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) { - if (SemaRef.TentativeDefinitions[i]->getPCHLevel() == 0) - AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions); - } - - // Build a record containing all of the file scoped decls in this file. - RecordData UnusedFileScopedDecls; - for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i) { - if (SemaRef.UnusedFileScopedDecls[i]->getPCHLevel() == 0) - AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls); - } - - // We write the entire table, overwriting the tables from the chain. - RecordData WeakUndeclaredIdentifiers; - if (!SemaRef.WeakUndeclaredIdentifiers.empty()) { - WeakUndeclaredIdentifiers.push_back( - SemaRef.WeakUndeclaredIdentifiers.size()); - for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator - I = SemaRef.WeakUndeclaredIdentifiers.begin(), - E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) { - AddIdentifierRef(I->first, WeakUndeclaredIdentifiers); - AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers); - WeakUndeclaredIdentifiers.push_back(I->second.getUsed()); - } - } - - // Build a record containing all of the locally-scoped external - // declarations in this header file. Generally, this record will be - // empty. - RecordData LocallyScopedExternalDecls; - // FIXME: This is filling in the PCH file in densemap order which is - // nondeterminstic! - for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator - TD = SemaRef.LocallyScopedExternalDecls.begin(), - TDEnd = SemaRef.LocallyScopedExternalDecls.end(); - TD != TDEnd; ++TD) { - if (TD->second->getPCHLevel() == 0) - AddDeclRef(TD->second, LocallyScopedExternalDecls); - } - - // Build a record containing all of the ext_vector declarations. - RecordData ExtVectorDecls; - for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) { - if (SemaRef.ExtVectorDecls[I]->getPCHLevel() == 0) - AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls); - } - - // Build a record containing all of the VTable uses information. - // We write everything here, because it's too hard to determine whether - // a use is new to this part. - RecordData VTableUses; - if (!SemaRef.VTableUses.empty()) { - VTableUses.push_back(SemaRef.VTableUses.size()); - for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { - AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); - AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); - VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); - } - } - - // Build a record containing all of dynamic classes declarations. - RecordData DynamicClasses; - for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I) - if (SemaRef.DynamicClasses[I]->getPCHLevel() == 0) - AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses); - - // Build a record containing all of pending implicit instantiations. - RecordData PendingImplicitInstantiations; - for (std::deque<Sema::PendingImplicitInstantiation>::iterator - I = SemaRef.PendingImplicitInstantiations.begin(), - N = SemaRef.PendingImplicitInstantiations.end(); I != N; ++I) { - if (I->first->getPCHLevel() == 0) { - AddDeclRef(I->first, PendingImplicitInstantiations); - AddSourceLocation(I->second, PendingImplicitInstantiations); - } - } - assert(SemaRef.PendingLocalImplicitInstantiations.empty() && - "There are local ones at end of translation unit!"); - - // Build a record containing some declaration references. - // It's not worth the effort to avoid duplication here. - RecordData SemaDeclRefs; - if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) { - AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); - AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); - } - - Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3); - WriteDeclsBlockAbbrevs(); - while (!DeclTypesToEmit.empty()) { - DeclOrType DOT = DeclTypesToEmit.front(); - DeclTypesToEmit.pop(); - if (DOT.isType()) - WriteType(DOT.getType()); - else - WriteDecl(Context, DOT.getDecl()); - } - Stream.ExitBlock(); - - WritePreprocessor(PP); - WriteSelectors(SemaRef); - WriteReferencedSelectorsPool(SemaRef); - WriteIdentifierTable(PP); - WriteTypeDeclOffsets(); - - /// Build a record containing first declarations from a chained PCH and the - /// most recent declarations in this PCH that they point to. - RecordData FirstLatestDeclIDs; - for (FirstLatestDeclMap::iterator - I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; ++I) { - assert(I->first->getPCHLevel() > I->second->getPCHLevel() && - "Expected first & second to be in different PCHs"); - AddDeclRef(I->first, FirstLatestDeclIDs); - AddDeclRef(I->second, FirstLatestDeclIDs); - } - if (!FirstLatestDeclIDs.empty()) - Stream.EmitRecord(pch::REDECLS_UPDATE_LATEST, FirstLatestDeclIDs); - - // Write the record containing external, unnamed definitions. - if (!ExternalDefinitions.empty()) - Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused file scoped decls. - if (!UnusedFileScopedDecls.empty()) - Stream.EmitRecord(pch::UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); - - // Write the record containing weak undeclared identifiers. - if (!WeakUndeclaredIdentifiers.empty()) - Stream.EmitRecord(pch::WEAK_UNDECLARED_IDENTIFIERS, - WeakUndeclaredIdentifiers); - - // Write the record containing locally-scoped external definitions. - if (!LocallyScopedExternalDecls.empty()) - Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS, - LocallyScopedExternalDecls); - - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(pch::VTABLE_USES, VTableUses); - - // Write the record containing dynamic classes declarations. - if (!DynamicClasses.empty()) - Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses); - - // Write the record containing pending implicit instantiations. - if (!PendingImplicitInstantiations.empty()) - Stream.EmitRecord(pch::PENDING_IMPLICIT_INSTANTIATIONS, - PendingImplicitInstantiations); - - // Write the record containing declaration references of Sema. - if (!SemaDeclRefs.empty()) - Stream.EmitRecord(pch::SEMA_DECL_REFS, SemaDeclRefs); - - Record.clear(); - Record.push_back(NumStatements); - Record.push_back(NumMacros); - Record.push_back(NumLexicalDeclContexts); - Record.push_back(NumVisibleDeclContexts); - WriteDeclUpdateBlock(); - Stream.EmitRecord(pch::STATISTICS, Record); - Stream.ExitBlock(); -} - -void PCHWriter::WriteDeclUpdateBlock() { - if (ReplacedDecls.empty()) - return; - - RecordData Record; - for (llvm::SmallVector<std::pair<pch::DeclID, uint64_t>, 16>::iterator - I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) { - Record.push_back(I->first); - Record.push_back(I->second); - } - Stream.EmitRecord(pch::DECL_REPLACEMENTS, Record); -} - -void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) { - Record.push_back(Loc.getRawEncoding()); -} - -void PCHWriter::AddSourceRange(SourceRange Range, RecordData &Record) { - AddSourceLocation(Range.getBegin(), Record); - AddSourceLocation(Range.getEnd(), Record); -} - -void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) { - Record.push_back(Value.getBitWidth()); - unsigned N = Value.getNumWords(); - const uint64_t* Words = Value.getRawData(); - for (unsigned I = 0; I != N; ++I) - Record.push_back(Words[I]); -} - -void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) { - Record.push_back(Value.isUnsigned()); - AddAPInt(Value, Record); -} - -void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) { - AddAPInt(Value.bitcastToAPInt(), Record); -} - -void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) { - Record.push_back(getIdentifierRef(II)); -} - -pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) { - if (II == 0) - return 0; - - pch::IdentID &ID = IdentifierIDs[II]; - if (ID == 0) - ID = NextIdentID++; - return ID; -} - -pch::IdentID PCHWriter::getMacroDefinitionID(MacroDefinition *MD) { - if (MD == 0) - return 0; - - pch::IdentID &ID = MacroDefinitions[MD]; - if (ID == 0) - ID = MacroDefinitions.size(); - return ID; -} - -void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) { - Record.push_back(getSelectorRef(SelRef)); -} - -pch::SelectorID PCHWriter::getSelectorRef(Selector Sel) { - if (Sel.getAsOpaquePtr() == 0) { - return 0; - } - - pch::SelectorID &SID = SelectorIDs[Sel]; - if (SID == 0 && Chain) { - // This might trigger a ReadSelector callback, which will set the ID for - // this selector. - Chain->LoadSelector(Sel); - } - if (SID == 0) { - SID = NextSelectorID++; - } - return SID; -} - -void PCHWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record) { - AddDeclRef(Temp->getDestructor(), Record); -} - -void PCHWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, - const TemplateArgumentLocInfo &Arg, - RecordData &Record) { - switch (Kind) { - case TemplateArgument::Expression: - AddStmt(Arg.getAsExpr()); - break; - case TemplateArgument::Type: - AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record); - break; - case TemplateArgument::Template: - AddSourceRange(Arg.getTemplateQualifierRange(), Record); - AddSourceLocation(Arg.getTemplateNameLoc(), Record); - break; - case TemplateArgument::Null: - case TemplateArgument::Integral: - case TemplateArgument::Declaration: - case TemplateArgument::Pack: - break; - } -} - -void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, - RecordData &Record) { - AddTemplateArgument(Arg.getArgument(), Record); - - if (Arg.getArgument().getKind() == TemplateArgument::Expression) { - bool InfoHasSameExpr - = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr(); - Record.push_back(InfoHasSameExpr); - if (InfoHasSameExpr) - return; // Avoid storing the same expr twice. - } - AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo(), - Record); -} - -void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) { - if (TInfo == 0) { - AddTypeRef(QualType(), Record); - return; - } - - AddTypeRef(TInfo->getType(), Record); - TypeLocWriter TLW(*this, Record); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) - TLW.Visit(TL); -} - -void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { - if (T.isNull()) { - Record.push_back(pch::PREDEF_TYPE_NULL_ID); - return; - } - - unsigned FastQuals = T.getLocalFastQualifiers(); - T.removeFastQualifiers(); - - if (T.hasLocalNonFastQualifiers()) { - pch::TypeID &ID = TypeIDs[T]; - if (ID == 0) { - // We haven't seen these qualifiers applied to this type before. - // Assign it a new ID. This is the only time we enqueue a - // qualified type, and it has no CV qualifiers. - ID = NextTypeID++; - DeclTypesToEmit.push(T); - } - - // Encode the type qualifiers in the type reference. - Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); - return; - } - - assert(!T.hasLocalQualifiers()); - - if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) { - pch::TypeID ID = 0; - switch (BT->getKind()) { - case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break; - case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break; - case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break; - case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break; - case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break; - case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break; - case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break; - case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break; - case BuiltinType::UInt128: ID = pch::PREDEF_TYPE_UINT128_ID; break; - case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break; - case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break; - case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break; - case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break; - case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break; - case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break; - case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break; - case BuiltinType::Int128: ID = pch::PREDEF_TYPE_INT128_ID; break; - case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break; - case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break; - case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break; - case BuiltinType::NullPtr: ID = pch::PREDEF_TYPE_NULLPTR_ID; break; - case BuiltinType::Char16: ID = pch::PREDEF_TYPE_CHAR16_ID; break; - case BuiltinType::Char32: ID = pch::PREDEF_TYPE_CHAR32_ID; break; - case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break; - case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break; - case BuiltinType::ObjCId: ID = pch::PREDEF_TYPE_OBJC_ID; break; - case BuiltinType::ObjCClass: ID = pch::PREDEF_TYPE_OBJC_CLASS; break; - case BuiltinType::ObjCSel: ID = pch::PREDEF_TYPE_OBJC_SEL; break; - case BuiltinType::UndeducedAuto: - assert(0 && "Should not see undeduced auto here"); - break; - } - - Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); - return; - } - - pch::TypeID &ID = TypeIDs[T]; - if (ID == 0) { - // We haven't seen this type before. Assign it a new ID and put it - // into the queue of types to emit. - ID = NextTypeID++; - DeclTypesToEmit.push(T); - } - - // Encode the type qualifiers in the type reference. - Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); -} - -void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) { - Record.push_back(GetDeclRef(D)); -} - -pch::DeclID PCHWriter::GetDeclRef(const Decl *D) { - if (D == 0) { - return 0; - } - - pch::DeclID &ID = DeclIDs[D]; - if (ID == 0) { - // We haven't seen this declaration before. Give it a new ID and - // enqueue it in the list of declarations to emit. - ID = NextDeclID++; - DeclTypesToEmit.push(const_cast<Decl *>(D)); - } else if (ID < FirstDeclID && D->isChangedSinceDeserialization()) { - // We don't add it to the replacement collection here, because we don't - // have the offset yet. - DeclTypesToEmit.push(const_cast<Decl *>(D)); - // Reset the flag, so that we don't add this decl multiple times. - const_cast<Decl *>(D)->setChangedSinceDeserialization(false); - } - - return ID; -} - -pch::DeclID PCHWriter::getDeclID(const Decl *D) { - if (D == 0) - return 0; - - assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"); - return DeclIDs[D]; -} - -void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) { - // FIXME: Emit a stable enum for NameKind. 0 = Identifier etc. - Record.push_back(Name.getNameKind()); - switch (Name.getNameKind()) { - case DeclarationName::Identifier: - AddIdentifierRef(Name.getAsIdentifierInfo(), Record); - break; - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - AddSelectorRef(Name.getObjCSelector(), Record); - break; - - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - AddTypeRef(Name.getCXXNameType(), Record); - break; - - case DeclarationName::CXXOperatorName: - Record.push_back(Name.getCXXOverloadedOperator()); - break; - - case DeclarationName::CXXLiteralOperatorName: - AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record); - break; - - case DeclarationName::CXXUsingDirective: - // No extra data to emit - break; - } -} - -void PCHWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, - RecordData &Record) { - // Nested name specifiers usually aren't too long. I think that 8 would - // typically accomodate the vast majority. - llvm::SmallVector<NestedNameSpecifier *, 8> NestedNames; - - // Push each of the NNS's onto a stack for serialization in reverse order. - while (NNS) { - NestedNames.push_back(NNS); - NNS = NNS->getPrefix(); - } - - Record.push_back(NestedNames.size()); - while(!NestedNames.empty()) { - NNS = NestedNames.pop_back_val(); - NestedNameSpecifier::SpecifierKind Kind = NNS->getKind(); - Record.push_back(Kind); - switch (Kind) { - case NestedNameSpecifier::Identifier: - AddIdentifierRef(NNS->getAsIdentifier(), Record); - break; - - case NestedNameSpecifier::Namespace: - AddDeclRef(NNS->getAsNamespace(), Record); - break; - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - AddTypeRef(QualType(NNS->getAsType(), 0), Record); - Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); - break; - - case NestedNameSpecifier::Global: - // Don't need to write an associated value. - break; - } - } -} - -void PCHWriter::AddTemplateName(TemplateName Name, RecordData &Record) { - TemplateName::NameKind Kind = Name.getKind(); - Record.push_back(Kind); - switch (Kind) { - case TemplateName::Template: - AddDeclRef(Name.getAsTemplateDecl(), Record); - break; - - case TemplateName::OverloadedTemplate: { - OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate(); - Record.push_back(OvT->size()); - for (OverloadedTemplateStorage::iterator I = OvT->begin(), E = OvT->end(); - I != E; ++I) - AddDeclRef(*I, Record); - break; - } - - case TemplateName::QualifiedTemplate: { - QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName(); - AddNestedNameSpecifier(QualT->getQualifier(), Record); - Record.push_back(QualT->hasTemplateKeyword()); - AddDeclRef(QualT->getTemplateDecl(), Record); - break; - } - - case TemplateName::DependentTemplate: { - DependentTemplateName *DepT = Name.getAsDependentTemplateName(); - AddNestedNameSpecifier(DepT->getQualifier(), Record); - Record.push_back(DepT->isIdentifier()); - if (DepT->isIdentifier()) - AddIdentifierRef(DepT->getIdentifier(), Record); - else - Record.push_back(DepT->getOperator()); - break; - } - } -} - -void PCHWriter::AddTemplateArgument(const TemplateArgument &Arg, - RecordData &Record) { - Record.push_back(Arg.getKind()); - switch (Arg.getKind()) { - case TemplateArgument::Null: - break; - case TemplateArgument::Type: - AddTypeRef(Arg.getAsType(), Record); - break; - case TemplateArgument::Declaration: - AddDeclRef(Arg.getAsDecl(), Record); - break; - case TemplateArgument::Integral: - AddAPSInt(*Arg.getAsIntegral(), Record); - AddTypeRef(Arg.getIntegralType(), Record); - break; - case TemplateArgument::Template: - AddTemplateName(Arg.getAsTemplate(), Record); - break; - case TemplateArgument::Expression: - AddStmt(Arg.getAsExpr()); - break; - case TemplateArgument::Pack: - Record.push_back(Arg.pack_size()); - for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end(); - I != E; ++I) - AddTemplateArgument(*I, Record); - break; - } -} - -void -PCHWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams, - RecordData &Record) { - assert(TemplateParams && "No TemplateParams!"); - AddSourceLocation(TemplateParams->getTemplateLoc(), Record); - AddSourceLocation(TemplateParams->getLAngleLoc(), Record); - AddSourceLocation(TemplateParams->getRAngleLoc(), Record); - Record.push_back(TemplateParams->size()); - for (TemplateParameterList::const_iterator - P = TemplateParams->begin(), PEnd = TemplateParams->end(); - P != PEnd; ++P) - AddDeclRef(*P, Record); -} - -/// \brief Emit a template argument list. -void -PCHWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, - RecordData &Record) { - assert(TemplateArgs && "No TemplateArgs!"); - Record.push_back(TemplateArgs->flat_size()); - for (int i=0, e = TemplateArgs->flat_size(); i != e; ++i) - AddTemplateArgument(TemplateArgs->get(i), Record); -} - - -void -PCHWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record) { - Record.push_back(Set.size()); - for (UnresolvedSetImpl::const_iterator - I = Set.begin(), E = Set.end(); I != E; ++I) { - AddDeclRef(I.getDecl(), Record); - Record.push_back(I.getAccess()); - } -} - -void PCHWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, - RecordData &Record) { - Record.push_back(Base.isVirtual()); - Record.push_back(Base.isBaseOfClass()); - Record.push_back(Base.getAccessSpecifierAsWritten()); - AddTypeSourceInfo(Base.getTypeSourceInfo(), Record); - AddSourceRange(Base.getSourceRange(), Record); -} - -void PCHWriter::AddCXXBaseOrMemberInitializers( - const CXXBaseOrMemberInitializer * const *BaseOrMembers, - unsigned NumBaseOrMembers, RecordData &Record) { - Record.push_back(NumBaseOrMembers); - for (unsigned i=0; i != NumBaseOrMembers; ++i) { - const CXXBaseOrMemberInitializer *Init = BaseOrMembers[i]; - - Record.push_back(Init->isBaseInitializer()); - if (Init->isBaseInitializer()) { - AddTypeSourceInfo(Init->getBaseClassInfo(), Record); - Record.push_back(Init->isBaseVirtual()); - } else { - AddDeclRef(Init->getMember(), Record); - } - AddSourceLocation(Init->getMemberLocation(), Record); - AddStmt(Init->getInit()); - AddDeclRef(Init->getAnonUnionMember(), Record); - AddSourceLocation(Init->getLParenLoc(), Record); - AddSourceLocation(Init->getRParenLoc(), Record); - Record.push_back(Init->isWritten()); - if (Init->isWritten()) { - Record.push_back(Init->getSourceOrder()); - } else { - Record.push_back(Init->getNumArrayIndices()); - for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i) - AddDeclRef(Init->getArrayIndex(i), Record); - } - } -} - -void PCHWriter::SetReader(PCHReader *Reader) { - assert(Reader && "Cannot remove chain"); - assert(FirstDeclID == NextDeclID && - FirstTypeID == NextTypeID && - FirstIdentID == NextIdentID && - FirstSelectorID == NextSelectorID && - "Setting chain after writing has started."); - Chain = Reader; -} - -void PCHWriter::IdentifierRead(pch::IdentID ID, IdentifierInfo *II) { - IdentifierIDs[II] = ID; -} - -void PCHWriter::TypeRead(pch::TypeID ID, QualType T) { - TypeIDs[T] = ID; -} - -void PCHWriter::DeclRead(pch::DeclID ID, const Decl *D) { - DeclIDs[D] = ID; -} - -void PCHWriter::SelectorRead(pch::SelectorID ID, Selector S) { - SelectorIDs[S] = ID; -} diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp deleted file mode 100644 index 9893d254e9e..00000000000 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ /dev/null @@ -1,1174 +0,0 @@ -//===--- PCHWriterDecl.cpp - Declaration Serialization --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements serialization for Declarations. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHWriter.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/Expr.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/ErrorHandling.h" -using namespace clang; - -//===----------------------------------------------------------------------===// -// Declaration serialization -//===----------------------------------------------------------------------===// - -namespace clang { - class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> { - - PCHWriter &Writer; - ASTContext &Context; - PCHWriter::RecordData &Record; - - public: - pch::DeclCode Code; - unsigned AbbrevToUse; - - PCHDeclWriter(PCHWriter &Writer, ASTContext &Context, - PCHWriter::RecordData &Record) - : Writer(Writer), Context(Context), Record(Record) { - } - - void Visit(Decl *D); - - void VisitDecl(Decl *D); - void VisitTranslationUnitDecl(TranslationUnitDecl *D); - void VisitNamedDecl(NamedDecl *D); - void VisitNamespaceDecl(NamespaceDecl *D); - void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - void VisitTypeDecl(TypeDecl *D); - void VisitTypedefDecl(TypedefDecl *D); - void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - void VisitTagDecl(TagDecl *D); - void VisitEnumDecl(EnumDecl *D); - void VisitRecordDecl(RecordDecl *D); - void VisitCXXRecordDecl(CXXRecordDecl *D); - void VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D); - void VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - void VisitValueDecl(ValueDecl *D); - void VisitEnumConstantDecl(EnumConstantDecl *D); - void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - void VisitDeclaratorDecl(DeclaratorDecl *D); - void VisitFunctionDecl(FunctionDecl *D); - void VisitCXXMethodDecl(CXXMethodDecl *D); - void VisitCXXConstructorDecl(CXXConstructorDecl *D); - void VisitCXXDestructorDecl(CXXDestructorDecl *D); - void VisitCXXConversionDecl(CXXConversionDecl *D); - void VisitFieldDecl(FieldDecl *D); - void VisitVarDecl(VarDecl *D); - void VisitImplicitParamDecl(ImplicitParamDecl *D); - void VisitParmVarDecl(ParmVarDecl *D); - void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - void VisitTemplateDecl(TemplateDecl *D); - void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); - void VisitClassTemplateDecl(ClassTemplateDecl *D); - void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); - void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - void VisitUsingDecl(UsingDecl *D); - void VisitUsingShadowDecl(UsingShadowDecl *D); - void VisitLinkageSpecDecl(LinkageSpecDecl *D); - void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); - void VisitAccessSpecDecl(AccessSpecDecl *D); - void VisitFriendDecl(FriendDecl *D); - void VisitFriendTemplateDecl(FriendTemplateDecl *D); - void VisitStaticAssertDecl(StaticAssertDecl *D); - void VisitBlockDecl(BlockDecl *D); - - void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, - uint64_t VisibleOffset); - template <typename T> void VisitRedeclarable(Redeclarable<T> *D); - - - // FIXME: Put in the same order is DeclNodes.td? - void VisitObjCMethodDecl(ObjCMethodDecl *D); - void VisitObjCContainerDecl(ObjCContainerDecl *D); - void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - void VisitObjCIvarDecl(ObjCIvarDecl *D); - void VisitObjCProtocolDecl(ObjCProtocolDecl *D); - void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); - void VisitObjCClassDecl(ObjCClassDecl *D); - void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); - void VisitObjCCategoryDecl(ObjCCategoryDecl *D); - void VisitObjCImplDecl(ObjCImplDecl *D); - void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); - void VisitObjCImplementationDecl(ObjCImplementationDecl *D); - void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); - void VisitObjCPropertyDecl(ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - }; -} - -void PCHDeclWriter::Visit(Decl *D) { - DeclVisitor<PCHDeclWriter>::Visit(D); - - // Handle FunctionDecl's body here and write it after all other Stmts/Exprs - // have been written. We want it last because we will not read it back when - // retrieving it from the PCH, we'll just lazily set the offset. - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - Record.push_back(FD->isThisDeclarationADefinition()); - if (FD->isThisDeclarationADefinition()) - Writer.AddStmt(FD->getBody()); - } -} - -void PCHDeclWriter::VisitDecl(Decl *D) { - Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record); - Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record); - Writer.AddSourceLocation(D->getLocation(), Record); - Record.push_back(D->isInvalidDecl()); - Record.push_back(D->hasAttrs()); - Record.push_back(D->isImplicit()); - Record.push_back(D->isUsed(false)); - Record.push_back(D->getAccess()); - Record.push_back(D->getPCHLevel()); -} - -void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { - VisitDecl(D); - Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - Code = pch::DECL_TRANSLATION_UNIT; -} - -void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) { - VisitDecl(D); - Writer.AddDeclarationName(D->getDeclName(), Record); -} - -void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) { - VisitNamedDecl(D); - Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); -} - -void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) { - VisitTypeDecl(D); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); - Code = pch::DECL_TYPEDEF; -} - -void PCHDeclWriter::VisitTagDecl(TagDecl *D) { - VisitTypeDecl(D); - Record.push_back(D->getIdentifierNamespace()); - VisitRedeclarable(D); - Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding - Record.push_back(D->isDefinition()); - Record.push_back(D->isEmbeddedInDeclarator()); - Writer.AddSourceLocation(D->getRBraceLoc(), Record); - Writer.AddSourceLocation(D->getTagKeywordLoc(), Record); - // FIXME: maybe write optional qualifier and its range. - Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); -} - -void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) { - VisitTagDecl(D); - Writer.AddTypeRef(D->getIntegerType(), Record); - Writer.AddTypeRef(D->getPromotionType(), Record); - Record.push_back(D->getNumPositiveBits()); - Record.push_back(D->getNumNegativeBits()); - Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record); - Code = pch::DECL_ENUM; -} - -void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) { - VisitTagDecl(D); - Record.push_back(D->hasFlexibleArrayMember()); - Record.push_back(D->isAnonymousStructOrUnion()); - Record.push_back(D->hasObjectMember()); - Code = pch::DECL_RECORD; -} - -void PCHDeclWriter::VisitValueDecl(ValueDecl *D) { - VisitNamedDecl(D); - Writer.AddTypeRef(D->getType(), Record); -} - -void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { - VisitValueDecl(D); - Record.push_back(D->getInitExpr()? 1 : 0); - if (D->getInitExpr()) - Writer.AddStmt(D->getInitExpr()); - Writer.AddAPSInt(D->getInitVal(), Record); - Code = pch::DECL_ENUM_CONSTANT; -} - -void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { - VisitValueDecl(D); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); - // FIXME: write optional qualifier and its range. -} - -void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { - VisitDeclaratorDecl(D); - // FIXME: write DeclarationNameLoc. - - Record.push_back(D->getIdentifierNamespace()); - Record.push_back(D->getTemplatedKind()); - switch (D->getTemplatedKind()) { - default: assert(false && "Unhandled TemplatedKind!"); - break; - case FunctionDecl::TK_NonTemplate: - break; - case FunctionDecl::TK_FunctionTemplate: - Writer.AddDeclRef(D->getDescribedFunctionTemplate(), Record); - break; - case FunctionDecl::TK_MemberSpecialization: { - MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo(); - Writer.AddDeclRef(MemberInfo->getInstantiatedFrom(), Record); - Record.push_back(MemberInfo->getTemplateSpecializationKind()); - Writer.AddSourceLocation(MemberInfo->getPointOfInstantiation(), Record); - break; - } - case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateSpecializationInfo * - FTSInfo = D->getTemplateSpecializationInfo(); - // We want it canonical to guarantee that it has a Common*. - Writer.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl(), Record); - Record.push_back(FTSInfo->getTemplateSpecializationKind()); - - // Template arguments. - Writer.AddTemplateArgumentList(FTSInfo->TemplateArguments, Record); - - // Template args as written. - Record.push_back(FTSInfo->TemplateArgumentsAsWritten != 0); - if (FTSInfo->TemplateArgumentsAsWritten) { - Record.push_back(FTSInfo->TemplateArgumentsAsWritten->size()); - for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->size(); i!=e; ++i) - Writer.AddTemplateArgumentLoc((*FTSInfo->TemplateArgumentsAsWritten)[i], - Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getLAngleLoc(), - Record); - Writer.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->getRAngleLoc(), - Record); - } - - Writer.AddSourceLocation(FTSInfo->getPointOfInstantiation(), Record); - break; - } - case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { - DependentFunctionTemplateSpecializationInfo * - DFTSInfo = D->getDependentSpecializationInfo(); - - // Templates. - Record.push_back(DFTSInfo->getNumTemplates()); - for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i) - Writer.AddDeclRef(DFTSInfo->getTemplate(i), Record); - - // Templates args. - Record.push_back(DFTSInfo->getNumTemplateArgs()); - for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i) - Writer.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i), Record); - Writer.AddSourceLocation(DFTSInfo->getLAngleLoc(), Record); - Writer.AddSourceLocation(DFTSInfo->getRAngleLoc(), Record); - break; - } - } - - // FunctionDecl's body is handled last at PCHWriterDecl::Visit, - // after everything else is written. - - VisitRedeclarable(D); - Record.push_back(D->getStorageClass()); // FIXME: stable encoding - Record.push_back(D->getStorageClassAsWritten()); - Record.push_back(D->isInlineSpecified()); - Record.push_back(D->isVirtualAsWritten()); - Record.push_back(D->isPure()); - Record.push_back(D->hasInheritedPrototype()); - Record.push_back(D->hasWrittenPrototype()); - Record.push_back(D->isDeleted()); - Record.push_back(D->isTrivial()); - Record.push_back(D->isCopyAssignment()); - Record.push_back(D->hasImplicitReturnZero()); - Writer.AddSourceLocation(D->getLocEnd(), Record); - - Record.push_back(D->param_size()); - for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Code = pch::DECL_FUNCTION; -} - -void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { - VisitNamedDecl(D); - // FIXME: convert to LazyStmtPtr? - // Unlike C/C++, method bodies will never be in header files. - bool HasBodyStuff = D->getBody() != 0 || - D->getSelfDecl() != 0 || D->getCmdDecl() != 0; - Record.push_back(HasBodyStuff); - if (HasBodyStuff) { - Writer.AddStmt(D->getBody()); - Writer.AddDeclRef(D->getSelfDecl(), Record); - Writer.AddDeclRef(D->getCmdDecl(), Record); - } - Record.push_back(D->isInstanceMethod()); - Record.push_back(D->isVariadic()); - Record.push_back(D->isSynthesized()); - Record.push_back(D->isDefined()); - // FIXME: stable encoding for @required/@optional - Record.push_back(D->getImplementationControl()); - // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway - Record.push_back(D->getObjCDeclQualifier()); - Record.push_back(D->getNumSelectorArgs()); - Writer.AddTypeRef(D->getResultType(), Record); - Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Record.push_back(D->param_size()); - for (ObjCMethodDecl::param_iterator P = D->param_begin(), - PEnd = D->param_end(); P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Code = pch::DECL_OBJC_METHOD; -} - -void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceRange(D->getAtEndRange(), Record); - // Abstract class (no need to define a stable pch::DECL code). -} - -void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { - VisitObjCContainerDecl(D); - Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); - Writer.AddDeclRef(D->getSuperClass(), Record); - Record.push_back(D->protocol_size()); - for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), - PEnd = D->protocol_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Record.push_back(D->ivar_size()); - for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), - IEnd = D->ivar_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - Writer.AddDeclRef(D->getCategoryList(), Record); - Record.push_back(D->isForwardDecl()); - Record.push_back(D->isImplicitInterfaceDecl()); - Writer.AddSourceLocation(D->getClassLoc(), Record); - Writer.AddSourceLocation(D->getSuperClassLoc(), Record); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Code = pch::DECL_OBJC_INTERFACE; -} - -void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { - VisitFieldDecl(D); - // FIXME: stable encoding for @public/@private/@protected/@package - Record.push_back(D->getAccessControl()); - Record.push_back(D->getSynthesize()); - Code = pch::DECL_OBJC_IVAR; -} - -void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { - VisitObjCContainerDecl(D); - Record.push_back(D->isForwardDecl()); - Writer.AddSourceLocation(D->getLocEnd(), Record); - Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Code = pch::DECL_OBJC_PROTOCOL; -} - -void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { - VisitFieldDecl(D); - Code = pch::DECL_OBJC_AT_DEFS_FIELD; -} - -void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) { - VisitDecl(D); - Record.push_back(D->size()); - for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) - Writer.AddDeclRef(I->getInterface(), Record); - for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) - Writer.AddSourceLocation(I->getLocation(), Record); - Code = pch::DECL_OBJC_CLASS; -} - -void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { - VisitDecl(D); - Record.push_back(D->protocol_size()); - for (ObjCForwardProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCForwardProtocolDecl::protocol_loc_iterator - PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Code = pch::DECL_OBJC_FORWARD_PROTOCOL; -} - -void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { - VisitObjCContainerDecl(D); - Writer.AddDeclRef(D->getClassInterface(), Record); - Record.push_back(D->protocol_size()); - for (ObjCCategoryDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCCategoryDecl::protocol_loc_iterator - PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - Writer.AddDeclRef(D->getNextClassCategory(), Record); - Writer.AddSourceLocation(D->getAtLoc(), Record); - Writer.AddSourceLocation(D->getCategoryNameLoc(), Record); - Code = pch::DECL_OBJC_CATEGORY; -} - -void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) { - VisitNamedDecl(D); - Writer.AddDeclRef(D->getClassInterface(), Record); - Code = pch::DECL_OBJC_COMPATIBLE_ALIAS; -} - -void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getAtLoc(), Record); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); - // FIXME: stable encoding - Record.push_back((unsigned)D->getPropertyAttributes()); - Record.push_back((unsigned)D->getPropertyAttributesAsWritten()); - // FIXME: stable encoding - Record.push_back((unsigned)D->getPropertyImplementation()); - Writer.AddDeclarationName(D->getGetterName(), Record); - Writer.AddDeclarationName(D->getSetterName(), Record); - Writer.AddDeclRef(D->getGetterMethodDecl(), Record); - Writer.AddDeclRef(D->getSetterMethodDecl(), Record); - Writer.AddDeclRef(D->getPropertyIvarDecl(), Record); - Code = pch::DECL_OBJC_PROPERTY; -} - -void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitObjCContainerDecl(D); - Writer.AddDeclRef(D->getClassInterface(), Record); - // Abstract class (no need to define a stable pch::DECL code). -} - -void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - VisitObjCImplDecl(D); - Writer.AddIdentifierRef(D->getIdentifier(), Record); - Code = pch::DECL_OBJC_CATEGORY_IMPL; -} - -void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { - VisitObjCImplDecl(D); - Writer.AddDeclRef(D->getSuperClass(), Record); - Writer.AddCXXBaseOrMemberInitializers(D->IvarInitializers, - D->NumIvarInitializers, Record); - Code = pch::DECL_OBJC_IMPLEMENTATION; -} - -void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - VisitDecl(D); - Writer.AddSourceLocation(D->getLocStart(), Record); - Writer.AddDeclRef(D->getPropertyDecl(), Record); - Writer.AddDeclRef(D->getPropertyIvarDecl(), Record); - Writer.AddStmt(D->getGetterCXXConstructor()); - Writer.AddStmt(D->getSetterCXXAssignment()); - Code = pch::DECL_OBJC_PROPERTY_IMPL; -} - -void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { - VisitDeclaratorDecl(D); - Record.push_back(D->isMutable()); - Record.push_back(D->getBitWidth()? 1 : 0); - if (D->getBitWidth()) - Writer.AddStmt(D->getBitWidth()); - if (!D->getDeclName()) - Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record); - Code = pch::DECL_FIELD; -} - -void PCHDeclWriter::VisitVarDecl(VarDecl *D) { - VisitDeclaratorDecl(D); - Record.push_back(D->getStorageClass()); // FIXME: stable encoding - Record.push_back(D->getStorageClassAsWritten()); - Record.push_back(D->isThreadSpecified()); - Record.push_back(D->hasCXXDirectInitializer()); - Record.push_back(D->isExceptionVariable()); - Record.push_back(D->isNRVOVariable()); - VisitRedeclarable(D); - Record.push_back(D->getInit() ? 1 : 0); - if (D->getInit()) - Writer.AddStmt(D->getInit()); - - MemberSpecializationInfo *SpecInfo - = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0; - Record.push_back(SpecInfo != 0); - if (SpecInfo) { - Writer.AddDeclRef(SpecInfo->getInstantiatedFrom(), Record); - Record.push_back(SpecInfo->getTemplateSpecializationKind()); - Writer.AddSourceLocation(SpecInfo->getPointOfInstantiation(), Record); - } - - Code = pch::DECL_VAR; -} - -void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { - VisitVarDecl(D); - Code = pch::DECL_IMPLICIT_PARAM; -} - -void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { - VisitVarDecl(D); - Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding - Record.push_back(D->hasInheritedDefaultArg()); - Record.push_back(D->hasUninstantiatedDefaultArg()); - if (D->hasUninstantiatedDefaultArg()) - Writer.AddStmt(D->getUninstantiatedDefaultArg()); - Code = pch::DECL_PARM_VAR; - - // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here - // we dynamically check for the properties that we optimize for, but don't - // know are true of all PARM_VAR_DECLs. - if (!D->getTypeSourceInfo() && - !D->hasAttrs() && - !D->isImplicit() && - !D->isUsed(false) && - D->getAccess() == AS_none && - D->getPCHLevel() == 0 && - D->getStorageClass() == 0 && - !D->hasCXXDirectInitializer() && // Can params have this ever? - D->getObjCDeclQualifier() == 0 && - !D->hasInheritedDefaultArg() && - D->getInit() == 0 && - !D->hasUninstantiatedDefaultArg()) // No default expr. - AbbrevToUse = Writer.getParmVarDeclAbbrev(); - - // Check things we know are true of *every* PARM_VAR_DECL, which is more than - // just us assuming it. - assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls"); - assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread"); - assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); - assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); - assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl"); - assert(!D->isStaticDataMember() && - "PARM_VAR_DECL can't be static data member"); -} - -void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { - VisitDecl(D); - Writer.AddStmt(D->getAsmString()); - Code = pch::DECL_FILE_SCOPE_ASM; -} - -void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) { - VisitDecl(D); - Writer.AddStmt(D->getBody()); - Writer.AddTypeSourceInfo(D->getSignatureAsWritten(), Record); - Record.push_back(D->param_size()); - for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Code = pch::DECL_BLOCK; -} - -void PCHDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { - VisitDecl(D); - // FIXME: It might be nice to serialize the brace locations for this - // declaration, which don't seem to be readily available in the AST. - Record.push_back(D->getLanguage()); - Record.push_back(D->hasBraces()); - Code = pch::DECL_LINKAGE_SPEC; -} - -void PCHDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getLBracLoc(), Record); - Writer.AddSourceLocation(D->getRBracLoc(), Record); - Writer.AddDeclRef(D->getNextNamespace(), Record); - - // Only write one reference--original or anonymous - Record.push_back(D->isOriginalNamespace()); - if (D->isOriginalNamespace()) - Writer.AddDeclRef(D->getAnonymousNamespace(), Record); - else - Writer.AddDeclRef(D->getOriginalNamespace(), Record); - Code = pch::DECL_NAMESPACE; - - if (Writer.hasChain() && !D->isOriginalNamespace() && - D->getOriginalNamespace()->getPCHLevel() > 0) { - Writer.AddUpdatedNamespace(D->getOriginalNamespace()); - } -} - -void PCHDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getAliasLoc(), Record); - Writer.AddSourceRange(D->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(D->getQualifier(), Record); - Writer.AddSourceLocation(D->getTargetNameLoc(), Record); - Writer.AddDeclRef(D->getNamespace(), Record); - Code = pch::DECL_NAMESPACE_ALIAS; -} - -void PCHDeclWriter::VisitUsingDecl(UsingDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceRange(D->getNestedNameRange(), Record); - Writer.AddSourceLocation(D->getUsingLocation(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record); - Record.push_back(D->getNumShadowDecls()); - for (UsingDecl::shadow_iterator P = D->shadow_begin(), - PEnd = D->shadow_end(); P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - Record.push_back(D->isTypeName()); - Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record); - Code = pch::DECL_USING; -} - -void PCHDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { - VisitNamedDecl(D); - Writer.AddDeclRef(D->getTargetDecl(), Record); - Writer.AddDeclRef(D->getUsingDecl(), Record); - Writer.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D), Record); - Code = pch::DECL_USING_SHADOW; -} - -void PCHDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - VisitNamedDecl(D); - Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record); - Writer.AddSourceRange(D->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(D->getQualifier(), Record); - Writer.AddSourceLocation(D->getIdentLocation(), Record); - Writer.AddDeclRef(D->getNominatedNamespace(), Record); - Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record); - Code = pch::DECL_USING_DIRECTIVE; -} - -void PCHDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - VisitValueDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); - Writer.AddSourceLocation(D->getUsingLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); - Code = pch::DECL_UNRESOLVED_USING_VALUE; -} - -void PCHDeclWriter::VisitUnresolvedUsingTypenameDecl( - UnresolvedUsingTypenameDecl *D) { - VisitTypeDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); - Writer.AddSourceLocation(D->getUsingLoc(), Record); - Writer.AddSourceLocation(D->getTypenameLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); - Code = pch::DECL_UNRESOLVED_USING_TYPENAME; -} - -void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { - // See comments at PCHDeclReader::VisitCXXRecordDecl about why this happens - // before VisitRecordDecl. - enum { Data_NoDefData, Data_Owner, Data_NotOwner }; - bool OwnsDefinitionData = false; - if (D->DefinitionData) { - assert(D->DefinitionData->Definition && - "DefinitionData don't point to a definition decl!"); - OwnsDefinitionData = D->DefinitionData->Definition == D; - if (OwnsDefinitionData) { - Record.push_back(Data_Owner); - } else { - Record.push_back(Data_NotOwner); - Writer.AddDeclRef(D->DefinitionData->Definition, Record); - } - } else - Record.push_back(Data_NoDefData); - - VisitRecordDecl(D); - - if (OwnsDefinitionData) { - assert(D->DefinitionData); - struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData; - - Record.push_back(Data.UserDeclaredConstructor); - Record.push_back(Data.UserDeclaredCopyConstructor); - Record.push_back(Data.UserDeclaredCopyAssignment); - Record.push_back(Data.UserDeclaredDestructor); - Record.push_back(Data.Aggregate); - Record.push_back(Data.PlainOldData); - Record.push_back(Data.Empty); - Record.push_back(Data.Polymorphic); - Record.push_back(Data.Abstract); - Record.push_back(Data.HasTrivialConstructor); - Record.push_back(Data.HasTrivialCopyConstructor); - Record.push_back(Data.HasTrivialCopyAssignment); - Record.push_back(Data.HasTrivialDestructor); - Record.push_back(Data.ComputedVisibleConversions); - Record.push_back(Data.DeclaredDefaultConstructor); - Record.push_back(Data.DeclaredCopyConstructor); - Record.push_back(Data.DeclaredCopyAssignment); - Record.push_back(Data.DeclaredDestructor); - - Record.push_back(D->getNumBases()); - for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), - E = D->bases_end(); I != E; ++I) - Writer.AddCXXBaseSpecifier(*I, Record); - - // FIXME: Make VBases lazily computed when needed to avoid storing them. - Record.push_back(D->getNumVBases()); - for (CXXRecordDecl::base_class_iterator I = D->vbases_begin(), - E = D->vbases_end(); I != E; ++I) - Writer.AddCXXBaseSpecifier(*I, Record); - - Writer.AddUnresolvedSet(Data.Conversions, Record); - Writer.AddUnresolvedSet(Data.VisibleConversions, Record); - // Data.Definition is written at the top. - Writer.AddDeclRef(Data.FirstFriend, Record); - } - - enum { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization - }; - if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) { - Record.push_back(CXXRecTemplate); - Writer.AddDeclRef(TemplD, Record); - } else if (MemberSpecializationInfo *MSInfo - = D->getMemberSpecializationInfo()) { - Record.push_back(CXXRecMemberSpecialization); - Writer.AddDeclRef(MSInfo->getInstantiatedFrom(), Record); - Record.push_back(MSInfo->getTemplateSpecializationKind()); - Writer.AddSourceLocation(MSInfo->getPointOfInstantiation(), Record); - } else { - Record.push_back(CXXRecNotTemplate); - } - - Code = pch::DECL_CXX_RECORD; -} - -void PCHDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { - VisitFunctionDecl(D); - Record.push_back(D->size_overridden_methods()); - for (CXXMethodDecl::method_iterator - I = D->begin_overridden_methods(), E = D->end_overridden_methods(); - I != E; ++I) - Writer.AddDeclRef(*I, Record); - Code = pch::DECL_CXX_METHOD; -} - -void PCHDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - VisitCXXMethodDecl(D); - - Record.push_back(D->IsExplicitSpecified); - Record.push_back(D->ImplicitlyDefined); - Writer.AddCXXBaseOrMemberInitializers(D->BaseOrMemberInitializers, - D->NumBaseOrMemberInitializers, Record); - - Code = pch::DECL_CXX_CONSTRUCTOR; -} - -void PCHDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - VisitCXXMethodDecl(D); - - Record.push_back(D->ImplicitlyDefined); - Writer.AddDeclRef(D->OperatorDelete, Record); - - Code = pch::DECL_CXX_DESTRUCTOR; -} - -void PCHDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { - VisitCXXMethodDecl(D); - Record.push_back(D->IsExplicitSpecified); - Code = pch::DECL_CXX_CONVERSION; -} - -void PCHDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) { - VisitDecl(D); - Writer.AddSourceLocation(D->getColonLoc(), Record); - Code = pch::DECL_ACCESS_SPEC; -} - -void PCHDeclWriter::VisitFriendDecl(FriendDecl *D) { - VisitDecl(D); - Record.push_back(D->Friend.is<TypeSourceInfo*>()); - if (D->Friend.is<TypeSourceInfo*>()) - Writer.AddTypeSourceInfo(D->Friend.get<TypeSourceInfo*>(), Record); - else - Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record); - Writer.AddDeclRef(D->NextFriend, Record); - Writer.AddSourceLocation(D->FriendLoc, Record); - Code = pch::DECL_FRIEND; -} - -void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) { - VisitDecl(D); - Record.push_back(D->getNumTemplateParameters()); - for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i) - Writer.AddTemplateParameterList(D->getTemplateParameterList(i), Record); - Record.push_back(D->getFriendDecl() != 0); - if (D->getFriendDecl()) - Writer.AddDeclRef(D->getFriendDecl(), Record); - else - Writer.AddTypeSourceInfo(D->getFriendType(), Record); - Writer.AddSourceLocation(D->getFriendLoc(), Record); - Code = pch::DECL_FRIEND_TEMPLATE; -} - -void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) { - VisitNamedDecl(D); - - Writer.AddDeclRef(D->getTemplatedDecl(), Record); - Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); -} - -void PCHDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { - VisitTemplateDecl(D); - - Record.push_back(D->getIdentifierNamespace()); - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - if (D->getPreviousDeclaration() == 0) { - // This TemplateDecl owns the CommonPtr; write it. - assert(D->isCanonicalDecl()); - - Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); - if (D->getInstantiatedFromMemberTemplate()) - Record.push_back(D->isMemberSpecialization()); - - Writer.AddDeclRef(D->getCommonPtr()->Latest, Record); - } else { - RedeclarableTemplateDecl *First = D->getFirstDeclaration(); - assert(First != D); - // If this is a most recent redeclaration that is pointed to by a first decl - // in a chained PCH, keep track of the association with the map so we can - // update the first decl during PCH reading. - if (First->getMostRecentDeclaration() == D && - First->getPCHLevel() > D->getPCHLevel()) { - assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end() - && "The latest is already set"); - Writer.FirstLatestDecls[First] = D; - } - } -} - -void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - - if (D->getPreviousDeclaration() == 0) { - typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy; - CTSDSetTy &CTSDSet = D->getSpecializations(); - Record.push_back(CTSDSet.size()); - for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - - typedef llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> CTPSDSetTy; - CTPSDSetTy &CTPSDSet = D->getPartialSpecializations(); - Record.push_back(CTPSDSet.size()); - for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - - // InjectedClassNameType is computed, no need to write it. - } - Code = pch::DECL_CLASS_TEMPLATE; -} - -void PCHDeclWriter::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - VisitCXXRecordDecl(D); - - llvm::PointerUnion<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *> InstFrom - = D->getSpecializedTemplateOrPartial(); - if (InstFrom.is<ClassTemplateDecl *>()) { - Writer.AddDeclRef(InstFrom.get<ClassTemplateDecl *>(), Record); - } else { - Writer.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>(), - Record); - Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record); - } - - // Explicit info. - Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record); - if (D->getTypeAsWritten()) { - Writer.AddSourceLocation(D->getExternLoc(), Record); - Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record); - } - - Writer.AddTemplateArgumentList(&D->getTemplateArgs(), Record); - Writer.AddSourceLocation(D->getPointOfInstantiation(), Record); - Record.push_back(D->getSpecializationKind()); - - if (D->isCanonicalDecl()) { - // When reading, we'll add it to the folding set of the following template. - Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record); - } - - Code = pch::DECL_CLASS_TEMPLATE_SPECIALIZATION; -} - -void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); - - Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); - - Record.push_back(D->getNumTemplateArgsAsWritten()); - for (int i = 0, e = D->getNumTemplateArgsAsWritten(); i != e; ++i) - Writer.AddTemplateArgumentLoc(D->getTemplateArgsAsWritten()[i], Record); - - Record.push_back(D->getSequenceNumber()); - - // These are read/set from/to the first declaration. - if (D->getPreviousDeclaration() == 0) { - Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); - Record.push_back(D->isMemberSpecialization()); - } - - Code = pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; -} - -void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); - - if (D->getPreviousDeclaration() == 0) { - // This FunctionTemplateDecl owns the CommonPtr; write it. - - // Write the function specialization declarations. - Record.push_back(D->getSpecializations().size()); - for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator - I = D->getSpecializations().begin(), - E = D->getSpecializations().end() ; I != E; ++I) { - assert(I->Function->isCanonicalDecl() && - "Expected only canonical decls in set"); - Writer.AddDeclRef(I->Function, Record); - } - } - Code = pch::DECL_FUNCTION_TEMPLATE; -} - -void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { - VisitTypeDecl(D); - - Record.push_back(D->wasDeclaredWithTypename()); - Record.push_back(D->isParameterPack()); - Record.push_back(D->defaultArgumentWasInherited()); - Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record); - - Code = pch::DECL_TEMPLATE_TYPE_PARM; -} - -void PCHDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { - VisitVarDecl(D); - // TemplateParmPosition. - Record.push_back(D->getDepth()); - Record.push_back(D->getPosition()); - // Rest of NonTypeTemplateParmDecl. - Record.push_back(D->getDefaultArgument() != 0); - if (D->getDefaultArgument()) { - Writer.AddStmt(D->getDefaultArgument()); - Record.push_back(D->defaultArgumentWasInherited()); - } - Code = pch::DECL_NON_TYPE_TEMPLATE_PARM; -} - -void PCHDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { - VisitTemplateDecl(D); - // TemplateParmPosition. - Record.push_back(D->getDepth()); - Record.push_back(D->getPosition()); - // Rest of TemplateTemplateParmDecl. - Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record); - Record.push_back(D->defaultArgumentWasInherited()); - Code = pch::DECL_TEMPLATE_TEMPLATE_PARM; -} - -void PCHDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { - VisitDecl(D); - Writer.AddStmt(D->getAssertExpr()); - Writer.AddStmt(D->getMessage()); - Code = pch::DECL_STATIC_ASSERT; -} - -/// \brief Emit the DeclContext part of a declaration context decl. -/// -/// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL -/// block for this declaration context is stored. May be 0 to indicate -/// that there are no declarations stored within this context. -/// -/// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE -/// block for this declaration context is stored. May be 0 to indicate -/// that there are no declarations visible from this context. Note -/// that this value will not be emitted for non-primary declaration -/// contexts. -void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, - uint64_t VisibleOffset) { - Record.push_back(LexicalOffset); - Record.push_back(VisibleOffset); -} - -template <typename T> -void PCHDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { - enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest }; - if (D->RedeclLink.getNext() == D) { - Record.push_back(NoRedeclaration); - } else { - Record.push_back(D->RedeclLink.NextIsPrevious() ? PointsToPrevious - : PointsToLatest); - Writer.AddDeclRef(D->RedeclLink.getPointer(), Record); - } - - T *First = D->getFirstDeclaration(); - T *ThisDecl = static_cast<T*>(D); - // If this is a most recent redeclaration that is pointed to by a first decl - // in a chained PCH, keep track of the association with the map so we can - // update the first decl during PCH reading. - if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl && - First->getPCHLevel() > ThisDecl->getPCHLevel()) { - assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end() - && "The latest is already set"); - Writer.FirstLatestDecls[First] = ThisDecl; - } -} - -//===----------------------------------------------------------------------===// -// PCHWriter Implementation -//===----------------------------------------------------------------------===// - -void PCHWriter::WriteDeclsBlockAbbrevs() { - using namespace llvm; - // Abbreviation for DECL_PARM_VAR. - BitCodeAbbrev *Abv = new BitCodeAbbrev(); - Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR)); - - // Decl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location - Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?) - Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs - Abv->Add(BitCodeAbbrevOp(0)); // isImplicit - Abv->Add(BitCodeAbbrevOp(0)); // isUsed - Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - Abv->Add(BitCodeAbbrevOp(0)); // PCH level - - // NamedDecl - Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name - // ValueDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type - // DeclaratorDecl - Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType - // VarDecl - Abv->Add(BitCodeAbbrevOp(0)); // StorageClass - Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten - Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified - Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer - Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable - Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable - Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl - Abv->Add(BitCodeAbbrevOp(0)); // HasInit - Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo - // ParmVarDecl - Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier - Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg - Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg - - ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv); - - Abv = new BitCodeAbbrev(); - Abv->Add(BitCodeAbbrevOp(pch::DECL_CONTEXT_LEXICAL)); - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - DeclContextLexicalAbbrev = Stream.EmitAbbrev(Abv); -} - -/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by -/// consumers of the AST. -/// -/// Such decls will always be deserialized from the PCH file, so we would like -/// this to be as restrictive as possible. Currently the predicate is driven by -/// code generation requirements, if other clients have a different notion of -/// what is "required" then we may have to consider an alternate scheme where -/// clients can iterate over the top-level decls and get information on them, -/// without necessary deserializing them. We could explicitly require such -/// clients to use a separate API call to "realize" the decl. This should be -/// relatively painless since they would presumably only do it for top-level -/// decls. -static bool isRequiredDecl(const Decl *D, ASTContext &Context) { - // File scoped assembly or obj-c implementation must be seen. - if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplementationDecl>(D)) - return true; - - return Context.DeclMustBeEmitted(D); -} - -void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) { - RecordData Record; - PCHDeclWriter W(*this, Context, Record); - - // If this declaration is also a DeclContext, write blocks for the - // declarations that lexically stored inside its context and those - // declarations that are visible from its context. These blocks - // are written before the declaration itself so that we can put - // their offsets into the record for the declaration. - uint64_t LexicalOffset = 0; - uint64_t VisibleOffset = 0; - DeclContext *DC = dyn_cast<DeclContext>(D); - if (DC) { - LexicalOffset = WriteDeclContextLexicalBlock(Context, DC); - VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); - } - - // Determine the ID for this declaration - pch::DeclID &IDR = DeclIDs[D]; - if (IDR == 0) - IDR = NextDeclID++; - pch::DeclID ID = IDR; - - if (ID < FirstDeclID) { - // We're replacing a decl in a previous file. - ReplacedDecls.push_back(std::make_pair(ID, Stream.GetCurrentBitNo())); - } else { - unsigned Index = ID - FirstDeclID; - - // Record the offset for this declaration - if (DeclOffsets.size() == Index) - DeclOffsets.push_back(Stream.GetCurrentBitNo()); - else if (DeclOffsets.size() < Index) { - DeclOffsets.resize(Index+1); - DeclOffsets[Index] = Stream.GetCurrentBitNo(); - } - } - - // Build and emit a record for this declaration - Record.clear(); - W.Code = (pch::DeclCode)0; - W.AbbrevToUse = 0; - W.Visit(D); - if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); - - if (!W.Code) - llvm::report_fatal_error(llvm::StringRef("unexpected declaration kind '") + - D->getDeclKindName() + "'"); - Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); - - // If the declaration had any attributes, write them now. - if (D->hasAttrs()) - WriteAttributeRecord(D->getAttrs()); - - // Flush any expressions that were written as part of this declaration. - FlushStmts(); - - // Note "external" declarations so that we can add them to a record in the - // PCH file later. - // - // FIXME: This should be renamed, the predicate is much more complicated. - if (isRequiredDecl(D, Context)) - ExternalDefinitions.push_back(ID); -} diff --git a/clang/lib/Frontend/PCHWriterStmt.cpp b/clang/lib/Frontend/PCHWriterStmt.cpp deleted file mode 100644 index 0c149f2c20f..00000000000 --- a/clang/lib/Frontend/PCHWriterStmt.cpp +++ /dev/null @@ -1,1370 +0,0 @@ -//===--- PCHWriterStmt.cpp - Statement and Expression Serialization -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements serialization for Statements and Expressions. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHWriter.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/StmtVisitor.h" -#include "llvm/Bitcode/BitstreamWriter.h" -using namespace clang; - -//===----------------------------------------------------------------------===// -// Statement/expression serialization -//===----------------------------------------------------------------------===// - -namespace clang { - class PCHStmtWriter : public StmtVisitor<PCHStmtWriter, void> { - PCHWriter &Writer; - PCHWriter::RecordData &Record; - - public: - pch::StmtCode Code; - - PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) - : Writer(Writer), Record(Record) { } - - void - AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args); - - void VisitStmt(Stmt *S); - void VisitNullStmt(NullStmt *S); - void VisitCompoundStmt(CompoundStmt *S); - void VisitSwitchCase(SwitchCase *S); - void VisitCaseStmt(CaseStmt *S); - void VisitDefaultStmt(DefaultStmt *S); - void VisitLabelStmt(LabelStmt *S); - void VisitIfStmt(IfStmt *S); - void VisitSwitchStmt(SwitchStmt *S); - void VisitWhileStmt(WhileStmt *S); - void VisitDoStmt(DoStmt *S); - void VisitForStmt(ForStmt *S); - void VisitGotoStmt(GotoStmt *S); - void VisitIndirectGotoStmt(IndirectGotoStmt *S); - void VisitContinueStmt(ContinueStmt *S); - void VisitBreakStmt(BreakStmt *S); - void VisitReturnStmt(ReturnStmt *S); - void VisitDeclStmt(DeclStmt *S); - void VisitAsmStmt(AsmStmt *S); - void VisitExpr(Expr *E); - void VisitPredefinedExpr(PredefinedExpr *E); - void VisitDeclRefExpr(DeclRefExpr *E); - void VisitIntegerLiteral(IntegerLiteral *E); - void VisitFloatingLiteral(FloatingLiteral *E); - void VisitImaginaryLiteral(ImaginaryLiteral *E); - void VisitStringLiteral(StringLiteral *E); - void VisitCharacterLiteral(CharacterLiteral *E); - void VisitParenExpr(ParenExpr *E); - void VisitParenListExpr(ParenListExpr *E); - void VisitUnaryOperator(UnaryOperator *E); - void VisitOffsetOfExpr(OffsetOfExpr *E); - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); - void VisitArraySubscriptExpr(ArraySubscriptExpr *E); - void VisitCallExpr(CallExpr *E); - void VisitMemberExpr(MemberExpr *E); - void VisitCastExpr(CastExpr *E); - void VisitBinaryOperator(BinaryOperator *E); - void VisitCompoundAssignOperator(CompoundAssignOperator *E); - void VisitConditionalOperator(ConditionalOperator *E); - void VisitImplicitCastExpr(ImplicitCastExpr *E); - void VisitExplicitCastExpr(ExplicitCastExpr *E); - void VisitCStyleCastExpr(CStyleCastExpr *E); - void VisitCompoundLiteralExpr(CompoundLiteralExpr *E); - void VisitExtVectorElementExpr(ExtVectorElementExpr *E); - void VisitInitListExpr(InitListExpr *E); - void VisitDesignatedInitExpr(DesignatedInitExpr *E); - void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); - void VisitVAArgExpr(VAArgExpr *E); - void VisitAddrLabelExpr(AddrLabelExpr *E); - void VisitStmtExpr(StmtExpr *E); - void VisitTypesCompatibleExpr(TypesCompatibleExpr *E); - void VisitChooseExpr(ChooseExpr *E); - void VisitGNUNullExpr(GNUNullExpr *E); - void VisitShuffleVectorExpr(ShuffleVectorExpr *E); - void VisitBlockExpr(BlockExpr *E); - void VisitBlockDeclRefExpr(BlockDeclRefExpr *E); - - // Objective-C Expressions - void VisitObjCStringLiteral(ObjCStringLiteral *E); - void VisitObjCEncodeExpr(ObjCEncodeExpr *E); - void VisitObjCSelectorExpr(ObjCSelectorExpr *E); - void VisitObjCProtocolExpr(ObjCProtocolExpr *E); - void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E); - void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E); - void VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E); - void VisitObjCMessageExpr(ObjCMessageExpr *E); - void VisitObjCSuperExpr(ObjCSuperExpr *E); - void VisitObjCIsaExpr(ObjCIsaExpr *E); - - // Objective-C Statements - void VisitObjCForCollectionStmt(ObjCForCollectionStmt *); - void VisitObjCAtCatchStmt(ObjCAtCatchStmt *); - void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); - void VisitObjCAtTryStmt(ObjCAtTryStmt *); - void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); - void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); - - // C++ Statements - void VisitCXXCatchStmt(CXXCatchStmt *S); - void VisitCXXTryStmt(CXXTryStmt *S); - - void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); - void VisitCXXMemberCallExpr(CXXMemberCallExpr *E); - void VisitCXXConstructExpr(CXXConstructExpr *E); - void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); - void VisitCXXNamedCastExpr(CXXNamedCastExpr *E); - void VisitCXXStaticCastExpr(CXXStaticCastExpr *E); - void VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E); - void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E); - void VisitCXXConstCastExpr(CXXConstCastExpr *E); - void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E); - void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); - void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); - void VisitCXXTypeidExpr(CXXTypeidExpr *E); - void VisitCXXThisExpr(CXXThisExpr *E); - void VisitCXXThrowExpr(CXXThrowExpr *E); - void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); - void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); - void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E); - - void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); - void VisitCXXNewExpr(CXXNewExpr *E); - void VisitCXXDeleteExpr(CXXDeleteExpr *E); - void VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); - - void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); - void VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); - void VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); - void VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); - - void VisitOverloadExpr(OverloadExpr *E); - void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); - void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); - - void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); - }; -} - -void PCHStmtWriter:: -AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args) { - Writer.AddSourceLocation(Args.LAngleLoc, Record); - Writer.AddSourceLocation(Args.RAngleLoc, Record); - for (unsigned i=0; i != Args.NumTemplateArgs; ++i) - Writer.AddTemplateArgumentLoc(Args.getTemplateArgs()[i], Record); -} - -void PCHStmtWriter::VisitStmt(Stmt *S) { -} - -void PCHStmtWriter::VisitNullStmt(NullStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getSemiLoc(), Record); - Code = pch::STMT_NULL; -} - -void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) { - VisitStmt(S); - Record.push_back(S->size()); - for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end(); - CS != CSEnd; ++CS) - Writer.AddStmt(*CS); - Writer.AddSourceLocation(S->getLBracLoc(), Record); - Writer.AddSourceLocation(S->getRBracLoc(), Record); - Code = pch::STMT_COMPOUND; -} - -void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) { - VisitStmt(S); - Record.push_back(Writer.getSwitchCaseID(S)); -} - -void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) { - VisitSwitchCase(S); - Writer.AddStmt(S->getLHS()); - Writer.AddStmt(S->getRHS()); - Writer.AddStmt(S->getSubStmt()); - Writer.AddSourceLocation(S->getCaseLoc(), Record); - Writer.AddSourceLocation(S->getEllipsisLoc(), Record); - Writer.AddSourceLocation(S->getColonLoc(), Record); - Code = pch::STMT_CASE; -} - -void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) { - VisitSwitchCase(S); - Writer.AddStmt(S->getSubStmt()); - Writer.AddSourceLocation(S->getDefaultLoc(), Record); - Writer.AddSourceLocation(S->getColonLoc(), Record); - Code = pch::STMT_DEFAULT; -} - -void PCHStmtWriter::VisitLabelStmt(LabelStmt *S) { - VisitStmt(S); - Writer.AddIdentifierRef(S->getID(), Record); - Writer.AddStmt(S->getSubStmt()); - Writer.AddSourceLocation(S->getIdentLoc(), Record); - Record.push_back(Writer.GetLabelID(S)); - Code = pch::STMT_LABEL; -} - -void PCHStmtWriter::VisitIfStmt(IfStmt *S) { - VisitStmt(S); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getThen()); - Writer.AddStmt(S->getElse()); - Writer.AddSourceLocation(S->getIfLoc(), Record); - Writer.AddSourceLocation(S->getElseLoc(), Record); - Code = pch::STMT_IF; -} - -void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) { - VisitStmt(S); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getSwitchLoc(), Record); - for (SwitchCase *SC = S->getSwitchCaseList(); SC; - SC = SC->getNextSwitchCase()) - Record.push_back(Writer.RecordSwitchCaseID(SC)); - Code = pch::STMT_SWITCH; -} - -void PCHStmtWriter::VisitWhileStmt(WhileStmt *S) { - VisitStmt(S); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getWhileLoc(), Record); - Code = pch::STMT_WHILE; -} - -void PCHStmtWriter::VisitDoStmt(DoStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getCond()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getDoLoc(), Record); - Writer.AddSourceLocation(S->getWhileLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_DO; -} - -void PCHStmtWriter::VisitForStmt(ForStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getInit()); - Writer.AddStmt(S->getCond()); - Writer.AddDeclRef(S->getConditionVariable(), Record); - Writer.AddStmt(S->getInc()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getForLoc(), Record); - Writer.AddSourceLocation(S->getLParenLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_FOR; -} - -void PCHStmtWriter::VisitGotoStmt(GotoStmt *S) { - VisitStmt(S); - Record.push_back(Writer.GetLabelID(S->getLabel())); - Writer.AddSourceLocation(S->getGotoLoc(), Record); - Writer.AddSourceLocation(S->getLabelLoc(), Record); - Code = pch::STMT_GOTO; -} - -void PCHStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getGotoLoc(), Record); - Writer.AddSourceLocation(S->getStarLoc(), Record); - Writer.AddStmt(S->getTarget()); - Code = pch::STMT_INDIRECT_GOTO; -} - -void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getContinueLoc(), Record); - Code = pch::STMT_CONTINUE; -} - -void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getBreakLoc(), Record); - Code = pch::STMT_BREAK; -} - -void PCHStmtWriter::VisitReturnStmt(ReturnStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getRetValue()); - Writer.AddSourceLocation(S->getReturnLoc(), Record); - Writer.AddDeclRef(S->getNRVOCandidate(), Record); - Code = pch::STMT_RETURN; -} - -void PCHStmtWriter::VisitDeclStmt(DeclStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getStartLoc(), Record); - Writer.AddSourceLocation(S->getEndLoc(), Record); - DeclGroupRef DG = S->getDeclGroup(); - for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D) - Writer.AddDeclRef(*D, Record); - Code = pch::STMT_DECL; -} - -void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) { - VisitStmt(S); - Record.push_back(S->getNumOutputs()); - Record.push_back(S->getNumInputs()); - Record.push_back(S->getNumClobbers()); - Writer.AddSourceLocation(S->getAsmLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Record.push_back(S->isVolatile()); - Record.push_back(S->isSimple()); - Record.push_back(S->isMSAsm()); - Writer.AddStmt(S->getAsmString()); - - // Outputs - for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { - Writer.AddIdentifierRef(S->getOutputIdentifier(I), Record); - Writer.AddStmt(S->getOutputConstraintLiteral(I)); - Writer.AddStmt(S->getOutputExpr(I)); - } - - // Inputs - for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) { - Writer.AddIdentifierRef(S->getInputIdentifier(I), Record); - Writer.AddStmt(S->getInputConstraintLiteral(I)); - Writer.AddStmt(S->getInputExpr(I)); - } - - // Clobbers - for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I) - Writer.AddStmt(S->getClobber(I)); - - Code = pch::STMT_ASM; -} - -void PCHStmtWriter::VisitExpr(Expr *E) { - VisitStmt(E); - Writer.AddTypeRef(E->getType(), Record); - Record.push_back(E->isTypeDependent()); - Record.push_back(E->isValueDependent()); -} - -void PCHStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->getIdentType()); // FIXME: stable encoding - Code = pch::EXPR_PREDEFINED; -} - -void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) { - VisitExpr(E); - - Record.push_back(E->hasQualifier()); - unsigned NumTemplateArgs = E->getNumTemplateArgs(); - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() && - "Template args list with no args ?"); - Record.push_back(NumTemplateArgs); - - if (E->hasQualifier()) { - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - } - - if (NumTemplateArgs) - AddExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList()); - - Writer.AddDeclRef(E->getDecl(), Record); - // FIXME: write DeclarationNameLoc. - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_DECL_REF; -} - -void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddAPInt(E->getValue(), Record); - Code = pch::EXPR_INTEGER_LITERAL; -} - -void PCHStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) { - VisitExpr(E); - Writer.AddAPFloat(E->getValue(), Record); - Record.push_back(E->isExact()); - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_FLOATING_LITERAL; -} - -void PCHStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_IMAGINARY_LITERAL; -} - -void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) { - VisitExpr(E); - Record.push_back(E->getByteLength()); - Record.push_back(E->getNumConcatenated()); - Record.push_back(E->isWide()); - // FIXME: String data should be stored as a blob at the end of the - // StringLiteral. However, we can't do so now because we have no - // provision for coping with abbreviations when we're jumping around - // the PCH file during deserialization. - Record.append(E->getString().begin(), E->getString().end()); - for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) - Writer.AddSourceLocation(E->getStrTokenLoc(I), Record); - Code = pch::EXPR_STRING_LITERAL; -} - -void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isWide()); - Code = pch::EXPR_CHARACTER_LITERAL; -} - -void PCHStmtWriter::VisitParenExpr(ParenExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLParen(), Record); - Writer.AddSourceLocation(E->getRParen(), Record); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_PAREN; -} - -void PCHStmtWriter::VisitParenListExpr(ParenListExpr *E) { - VisitExpr(E); - Record.push_back(E->NumExprs); - for (unsigned i=0; i != E->NumExprs; ++i) - Writer.AddStmt(E->Exprs[i]); - Writer.AddSourceLocation(E->LParenLoc, Record); - Writer.AddSourceLocation(E->RParenLoc, Record); - Code = pch::EXPR_PAREN_LIST; -} - -void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Code = pch::EXPR_UNARY_OPERATOR; -} - -void PCHStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumComponents()); - Record.push_back(E->getNumExpressions()); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); - for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { - const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I); - Record.push_back(ON.getKind()); // FIXME: Stable encoding - Writer.AddSourceLocation(ON.getRange().getBegin(), Record); - Writer.AddSourceLocation(ON.getRange().getEnd(), Record); - switch (ON.getKind()) { - case OffsetOfExpr::OffsetOfNode::Array: - Record.push_back(ON.getArrayExprIndex()); - break; - - case OffsetOfExpr::OffsetOfNode::Field: - Writer.AddDeclRef(ON.getField(), Record); - break; - - case OffsetOfExpr::OffsetOfNode::Identifier: - Writer.AddIdentifierRef(ON.getFieldName(), Record); - break; - - case OffsetOfExpr::OffsetOfNode::Base: - Writer.AddCXXBaseSpecifier(*ON.getBase(), Record); - break; - } - } - for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) - Writer.AddStmt(E->getIndexExpr(I)); - Code = pch::EXPR_OFFSETOF; -} - -void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { - VisitExpr(E); - Record.push_back(E->isSizeOf()); - if (E->isArgumentType()) - Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record); - else { - Record.push_back(0); - Writer.AddStmt(E->getArgumentExpr()); - } - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_SIZEOF_ALIGN_OF; -} - -void PCHStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Writer.AddSourceLocation(E->getRBracketLoc(), Record); - Code = pch::EXPR_ARRAY_SUBSCRIPT; -} - -void PCHStmtWriter::VisitCallExpr(CallExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Writer.AddStmt(E->getCallee()); - for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) - Writer.AddStmt(*Arg); - Code = pch::EXPR_CALL; -} - -void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) { - // Don't call VisitExpr, we'll write everything here. - - Record.push_back(E->hasQualifier()); - if (E->hasQualifier()) { - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - } - - unsigned NumTemplateArgs = E->getNumTemplateArgs(); - assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() && - "Template args list with no args ?"); - Record.push_back(NumTemplateArgs); - if (NumTemplateArgs) { - Writer.AddSourceLocation(E->getLAngleLoc(), Record); - Writer.AddSourceLocation(E->getRAngleLoc(), Record); - for (unsigned i=0; i != NumTemplateArgs; ++i) - Writer.AddTemplateArgumentLoc(E->getTemplateArgs()[i], Record); - } - - DeclAccessPair FoundDecl = E->getFoundDecl(); - Writer.AddDeclRef(FoundDecl.getDecl(), Record); - Record.push_back(FoundDecl.getAccess()); - - Writer.AddTypeRef(E->getType(), Record); - Writer.AddStmt(E->getBase()); - Writer.AddDeclRef(E->getMemberDecl(), Record); - // FIXME: write DeclarationNameLoc. - Writer.AddSourceLocation(E->getMemberLoc(), Record); - Record.push_back(E->isArrow()); - Code = pch::EXPR_MEMBER; -} - -void PCHStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getBase()); - Writer.AddSourceLocation(E->getIsaMemberLoc(), Record); - Record.push_back(E->isArrow()); - Code = pch::EXPR_OBJC_ISA; -} - -void PCHStmtWriter::VisitCastExpr(CastExpr *E) { - VisitExpr(E); - Record.push_back(E->path_size()); - Writer.AddStmt(E->getSubExpr()); - Record.push_back(E->getCastKind()); // FIXME: stable encoding - - for (CastExpr::path_iterator - PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI) - Writer.AddCXXBaseSpecifier(**PI, Record); -} - -void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) { - VisitExpr(E); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Record.push_back(E->getOpcode()); // FIXME: stable encoding - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Code = pch::EXPR_BINARY_OPERATOR; -} - -void PCHStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { - VisitBinaryOperator(E); - Writer.AddTypeRef(E->getComputationLHSType(), Record); - Writer.AddTypeRef(E->getComputationResultType(), Record); - Code = pch::EXPR_COMPOUND_ASSIGN_OPERATOR; -} - -void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) { - VisitExpr(E); - Writer.AddStmt(E->getCond()); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Writer.AddSourceLocation(E->getQuestionLoc(), Record); - Writer.AddSourceLocation(E->getColonLoc(), Record); - Code = pch::EXPR_CONDITIONAL_OPERATOR; -} - -void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) { - VisitCastExpr(E); - Record.push_back(E->getCategory()); - Code = pch::EXPR_IMPLICIT_CAST; -} - -void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) { - VisitCastExpr(E); - Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record); -} - -void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) { - VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CSTYLE_CAST; -} - -void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); - Writer.AddStmt(E->getInitializer()); - Record.push_back(E->isFileScope()); - Code = pch::EXPR_COMPOUND_LITERAL; -} - -void PCHStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getBase()); - Writer.AddIdentifierRef(&E->getAccessor(), Record); - Writer.AddSourceLocation(E->getAccessorLoc(), Record); - Code = pch::EXPR_EXT_VECTOR_ELEMENT; -} - -void PCHStmtWriter::VisitInitListExpr(InitListExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumInits()); - for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) - Writer.AddStmt(E->getInit(I)); - Writer.AddStmt(E->getSyntacticForm()); - Writer.AddSourceLocation(E->getLBraceLoc(), Record); - Writer.AddSourceLocation(E->getRBraceLoc(), Record); - Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record); - Record.push_back(E->hadArrayRangeDesignator()); - Code = pch::EXPR_INIT_LIST; -} - -void PCHStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumSubExprs()); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) - Writer.AddStmt(E->getSubExpr(I)); - Writer.AddSourceLocation(E->getEqualOrColonLoc(), Record); - Record.push_back(E->usesGNUSyntax()); - for (DesignatedInitExpr::designators_iterator D = E->designators_begin(), - DEnd = E->designators_end(); - D != DEnd; ++D) { - if (D->isFieldDesignator()) { - if (FieldDecl *Field = D->getField()) { - Record.push_back(pch::DESIG_FIELD_DECL); - Writer.AddDeclRef(Field, Record); - } else { - Record.push_back(pch::DESIG_FIELD_NAME); - Writer.AddIdentifierRef(D->getFieldName(), Record); - } - Writer.AddSourceLocation(D->getDotLoc(), Record); - Writer.AddSourceLocation(D->getFieldLoc(), Record); - } else if (D->isArrayDesignator()) { - Record.push_back(pch::DESIG_ARRAY); - Record.push_back(D->getFirstExprIndex()); - Writer.AddSourceLocation(D->getLBracketLoc(), Record); - Writer.AddSourceLocation(D->getRBracketLoc(), Record); - } else { - assert(D->isArrayRangeDesignator() && "Unknown designator"); - Record.push_back(pch::DESIG_ARRAY_RANGE); - Record.push_back(D->getFirstExprIndex()); - Writer.AddSourceLocation(D->getLBracketLoc(), Record); - Writer.AddSourceLocation(D->getEllipsisLoc(), Record); - Writer.AddSourceLocation(D->getRBracketLoc(), Record); - } - } - Code = pch::EXPR_DESIGNATED_INIT; -} - -void PCHStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - VisitExpr(E); - Code = pch::EXPR_IMPLICIT_VALUE_INIT; -} - -void PCHStmtWriter::VisitVAArgExpr(VAArgExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Writer.AddTypeSourceInfo(E->getWrittenTypeInfo(), Record); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_VA_ARG; -} - -void PCHStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getAmpAmpLoc(), Record); - Writer.AddSourceLocation(E->getLabelLoc(), Record); - Record.push_back(Writer.GetLabelID(E->getLabel())); - Code = pch::EXPR_ADDR_LABEL; -} - -void PCHStmtWriter::VisitStmtExpr(StmtExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubStmt()); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_STMT; -} - -void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) { - VisitExpr(E); - Writer.AddTypeSourceInfo(E->getArgTInfo1(), Record); - Writer.AddTypeSourceInfo(E->getArgTInfo2(), Record); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_TYPES_COMPATIBLE; -} - -void PCHStmtWriter::VisitChooseExpr(ChooseExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getCond()); - Writer.AddStmt(E->getLHS()); - Writer.AddStmt(E->getRHS()); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CHOOSE; -} - -void PCHStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getTokenLocation(), Record); - Code = pch::EXPR_GNU_NULL; -} - -void PCHStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumSubExprs()); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) - Writer.AddStmt(E->getExpr(I)); - Writer.AddSourceLocation(E->getBuiltinLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_SHUFFLE_VECTOR; -} - -void PCHStmtWriter::VisitBlockExpr(BlockExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getBlockDecl(), Record); - Record.push_back(E->hasBlockDeclRefExprs()); - Code = pch::EXPR_BLOCK; -} - -void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getDecl(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isByRef()); - Record.push_back(E->isConstQualAdded()); - Writer.AddStmt(E->getCopyConstructorExpr()); - Code = pch::EXPR_BLOCK_DECL_REF; -} - -//===----------------------------------------------------------------------===// -// Objective-C Expressions and Statements. -//===----------------------------------------------------------------------===// - -void PCHStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) { - VisitExpr(E); - Writer.AddStmt(E->getString()); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Code = pch::EXPR_OBJC_STRING_LITERAL; -} - -void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { - VisitExpr(E); - Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_OBJC_ENCODE; -} - -void PCHStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - VisitExpr(E); - Writer.AddSelectorRef(E->getSelector(), Record); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_OBJC_SELECTOR_EXPR; -} - -void PCHStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getProtocol(), Record); - Writer.AddSourceLocation(E->getAtLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_OBJC_PROTOCOL_EXPR; -} - -void PCHStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getDecl(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddStmt(E->getBase()); - Record.push_back(E->isArrow()); - Record.push_back(E->isFreeIvar()); - Code = pch::EXPR_OBJC_IVAR_REF_EXPR; -} - -void PCHStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getProperty(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddStmt(E->getBase()); - Code = pch::EXPR_OBJC_PROPERTY_REF_EXPR; -} - -void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E) { - VisitExpr(E); - Writer.AddDeclRef(E->getGetterMethod(), Record); - Writer.AddDeclRef(E->getSetterMethod(), Record); - - // NOTE: InterfaceDecl and Base are mutually exclusive. - Writer.AddDeclRef(E->getInterfaceDecl(), Record); - Writer.AddStmt(E->getBase()); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddSourceLocation(E->getClassLoc(), Record); - Code = pch::EXPR_OBJC_KVC_REF_EXPR; -} - -void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding - switch (E->getReceiverKind()) { - case ObjCMessageExpr::Instance: - Writer.AddStmt(E->getInstanceReceiver()); - break; - - case ObjCMessageExpr::Class: - Writer.AddTypeSourceInfo(E->getClassReceiverTypeInfo(), Record); - break; - - case ObjCMessageExpr::SuperClass: - case ObjCMessageExpr::SuperInstance: - Writer.AddTypeRef(E->getSuperType(), Record); - Writer.AddSourceLocation(E->getSuperLoc(), Record); - break; - } - - if (E->getMethodDecl()) { - Record.push_back(1); - Writer.AddDeclRef(E->getMethodDecl(), Record); - } else { - Record.push_back(0); - Writer.AddSelectorRef(E->getSelector(), Record); - } - - Writer.AddSourceLocation(E->getLeftLoc(), Record); - Writer.AddSourceLocation(E->getRightLoc(), Record); - - for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) - Writer.AddStmt(*Arg); - Code = pch::EXPR_OBJC_MESSAGE_EXPR; -} - -void PCHStmtWriter::VisitObjCSuperExpr(ObjCSuperExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLoc(), Record); - Code = pch::EXPR_OBJC_SUPER_EXPR; -} - -void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - VisitStmt(S); - Writer.AddStmt(S->getElement()); - Writer.AddStmt(S->getCollection()); - Writer.AddStmt(S->getBody()); - Writer.AddSourceLocation(S->getForLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_OBJC_FOR_COLLECTION; -} - -void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - Writer.AddStmt(S->getCatchBody()); - Writer.AddDeclRef(S->getCatchParamDecl(), Record); - Writer.AddSourceLocation(S->getAtCatchLoc(), Record); - Writer.AddSourceLocation(S->getRParenLoc(), Record); - Code = pch::STMT_OBJC_CATCH; -} - -void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - Writer.AddStmt(S->getFinallyBody()); - Writer.AddSourceLocation(S->getAtFinallyLoc(), Record); - Code = pch::STMT_OBJC_FINALLY; -} - -void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - Record.push_back(S->getNumCatchStmts()); - Record.push_back(S->getFinallyStmt() != 0); - Writer.AddStmt(S->getTryBody()); - for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) - Writer.AddStmt(S->getCatchStmt(I)); - if (S->getFinallyStmt()) - Writer.AddStmt(S->getFinallyStmt()); - Writer.AddSourceLocation(S->getAtTryLoc(), Record); - Code = pch::STMT_OBJC_AT_TRY; -} - -void PCHStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { - Writer.AddStmt(S->getSynchExpr()); - Writer.AddStmt(S->getSynchBody()); - Writer.AddSourceLocation(S->getAtSynchronizedLoc(), Record); - Code = pch::STMT_OBJC_AT_SYNCHRONIZED; -} - -void PCHStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - Writer.AddStmt(S->getThrowExpr()); - Writer.AddSourceLocation(S->getThrowLoc(), Record); - Code = pch::STMT_OBJC_AT_THROW; -} - -//===----------------------------------------------------------------------===// -// C++ Expressions and Statements. -//===----------------------------------------------------------------------===// - -void PCHStmtWriter::VisitCXXCatchStmt(CXXCatchStmt *S) { - VisitStmt(S); - Writer.AddSourceLocation(S->getCatchLoc(), Record); - Writer.AddDeclRef(S->getExceptionDecl(), Record); - Writer.AddStmt(S->getHandlerBlock()); - Code = pch::STMT_CXX_CATCH; -} - -void PCHStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) { - VisitStmt(S); - Record.push_back(S->getNumHandlers()); - Writer.AddSourceLocation(S->getTryLoc(), Record); - Writer.AddStmt(S->getTryBlock()); - for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i) - Writer.AddStmt(S->getHandler(i)); - Code = pch::STMT_CXX_TRY; -} - -void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - VisitCallExpr(E); - Record.push_back(E->getOperator()); - Code = pch::EXPR_CXX_OPERATOR_CALL; -} - -void PCHStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - VisitCallExpr(E); - Code = pch::EXPR_CXX_MEMBER_CALL; -} - -void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { - VisitExpr(E); - Record.push_back(E->getNumArgs()); - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) - Writer.AddStmt(E->getArg(I)); - Writer.AddDeclRef(E->getConstructor(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isElidable()); - Record.push_back(E->requiresZeroInitialization()); - Record.push_back(E->getConstructionKind()); // FIXME: stable encoding - Code = pch::EXPR_CXX_CONSTRUCT; -} - -void PCHStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { - VisitCXXConstructExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_TEMPORARY_OBJECT; -} - -void PCHStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); -} - -void PCHStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_STATIC_CAST; -} - -void PCHStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_DYNAMIC_CAST; -} - -void PCHStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_REINTERPRET_CAST; -} - -void PCHStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) { - VisitCXXNamedCastExpr(E); - Code = pch::EXPR_CXX_CONST_CAST; -} - -void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { - VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_FUNCTIONAL_CAST; -} - -void PCHStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - VisitExpr(E); - Record.push_back(E->getValue()); - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_CXX_BOOL_LITERAL; -} - -void PCHStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Code = pch::EXPR_CXX_NULL_PTR_LITERAL; -} - -void PCHStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - VisitExpr(E); - Writer.AddSourceRange(E->getSourceRange(), Record); - if (E->isTypeOperand()) { - Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record); - Code = pch::EXPR_CXX_TYPEID_TYPE; - } else { - Writer.AddStmt(E->getExprOperand()); - Code = pch::EXPR_CXX_TYPEID_EXPR; - } -} - -void PCHStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getLocation(), Record); - Record.push_back(E->isImplicit()); - Code = pch::EXPR_CXX_THIS; -} - -void PCHStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getThrowLoc(), Record); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_CXX_THROW; -} - -void PCHStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - VisitExpr(E); - - bool HasOtherExprStored = E->Param.getInt(); - // Store these first, the reader reads them before creation. - Record.push_back(HasOtherExprStored); - if (HasOtherExprStored) - Writer.AddStmt(E->getExpr()); - Writer.AddDeclRef(E->getParam(), Record); - Writer.AddSourceLocation(E->getUsedLocation(), Record); - - Code = pch::EXPR_CXX_DEFAULT_ARG; -} - -void PCHStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - VisitExpr(E); - Writer.AddCXXTemporary(E->getTemporary(), Record); - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_CXX_BIND_TEMPORARY; -} - -void PCHStmtWriter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) { - VisitExpr(E); - Writer.AddStmt(E->getSubExpr()); - Record.push_back(E->extendsLifetime()); - Record.push_back(E->requiresTemporaryCopy()); - Code = pch::EXPR_CXX_BIND_REFERENCE; -} - -void PCHStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - VisitExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_SCALAR_VALUE_INIT; -} - -void PCHStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { - VisitExpr(E); - Record.push_back(E->isGlobalNew()); - Record.push_back(E->hasInitializer()); - Record.push_back(E->isArray()); - Record.push_back(E->getNumPlacementArgs()); - Record.push_back(E->getNumConstructorArgs()); - Writer.AddDeclRef(E->getOperatorNew(), Record); - Writer.AddDeclRef(E->getOperatorDelete(), Record); - Writer.AddDeclRef(E->getConstructor(), Record); - Writer.AddSourceRange(E->getTypeIdParens(), Record); - Writer.AddSourceLocation(E->getStartLoc(), Record); - Writer.AddSourceLocation(E->getEndLoc(), Record); - for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); - I != e; ++I) - Writer.AddStmt(*I); - - Code = pch::EXPR_CXX_NEW; -} - -void PCHStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - VisitExpr(E); - Record.push_back(E->isGlobalDelete()); - Record.push_back(E->isArrayForm()); - Writer.AddDeclRef(E->getOperatorDelete(), Record); - Writer.AddStmt(E->getArgument()); - Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record); - - Code = pch::EXPR_CXX_DELETE; -} - -void PCHStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { - VisitExpr(E); - - Writer.AddStmt(E->getBase()); - Record.push_back(E->isArrow()); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record); - Writer.AddSourceLocation(E->getColonColonLoc(), Record); - Writer.AddSourceLocation(E->getTildeLoc(), Record); - - // PseudoDestructorTypeStorage. - Writer.AddIdentifierRef(E->getDestroyedTypeIdentifier(), Record); - if (E->getDestroyedTypeIdentifier()) - Writer.AddSourceLocation(E->getDestroyedTypeLoc(), Record); - else - Writer.AddTypeSourceInfo(E->getDestroyedTypeInfo(), Record); - - Code = pch::EXPR_CXX_PSEUDO_DESTRUCTOR; -} - -void PCHStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - VisitExpr(E); - Record.push_back(E->getNumTemporaries()); - for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i) - Writer.AddCXXTemporary(E->getTemporary(i), Record); - - Writer.AddStmt(E->getSubExpr()); - Code = pch::EXPR_CXX_EXPR_WITH_TEMPORARIES; -} - -void -PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){ - VisitExpr(E); - - // Don't emit anything here, NumTemplateArgs must be emitted first. - - if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args - = *E->getExplicitTemplateArgumentList(); - assert(Args.NumTemplateArgs && - "Num of template args was zero! PCH reading will mess up!"); - Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); - } else { - Record.push_back(0); - } - - if (!E->isImplicitAccess()) - Writer.AddStmt(E->getBase()); - else - Writer.AddStmt(0); - Writer.AddTypeRef(E->getBaseType(), Record); - Record.push_back(E->isArrow()); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record); - // FIXME: write whole DeclarationNameInfo. - Writer.AddDeclarationName(E->getMember(), Record); - Writer.AddSourceLocation(E->getMemberLoc(), Record); - Code = pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER; -} - -void -PCHStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - VisitExpr(E); - - // Don't emit anything here, NumTemplateArgs must be emitted first. - - if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs(); - assert(Args.NumTemplateArgs && - "Num of template args was zero! PCH reading will mess up!"); - Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); - } else { - Record.push_back(0); - } - - // FIXME: write whole DeclarationNameInfo. - Writer.AddDeclarationName(E->getDeclName(), Record); - Writer.AddSourceLocation(E->getLocation(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Code = pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF; -} - -void -PCHStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) { - VisitExpr(E); - Record.push_back(E->arg_size()); - for (CXXUnresolvedConstructExpr::arg_iterator - ArgI = E->arg_begin(), ArgE = E->arg_end(); ArgI != ArgE; ++ArgI) - Writer.AddStmt(*ArgI); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); - Writer.AddTypeRef(E->getTypeAsWritten(), Record); - Writer.AddSourceLocation(E->getLParenLoc(), Record); - Writer.AddSourceLocation(E->getRParenLoc(), Record); - Code = pch::EXPR_CXX_UNRESOLVED_CONSTRUCT; -} - -void PCHStmtWriter::VisitOverloadExpr(OverloadExpr *E) { - VisitExpr(E); - - // Don't emit anything here, NumTemplateArgs must be emitted first. - - if (E->hasExplicitTemplateArgs()) { - const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs(); - assert(Args.NumTemplateArgs && - "Num of template args was zero! PCH reading will mess up!"); - Record.push_back(Args.NumTemplateArgs); - AddExplicitTemplateArgumentList(Args); - } else { - Record.push_back(0); - } - - Record.push_back(E->getNumDecls()); - for (OverloadExpr::decls_iterator - OvI = E->decls_begin(), OvE = E->decls_end(); OvI != OvE; ++OvI) { - Writer.AddDeclRef(OvI.getDecl(), Record); - Record.push_back(OvI.getAccess()); - } - - // FIXME: write whole DeclarationNameInfo. - Writer.AddDeclarationName(E->getName(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddSourceLocation(E->getNameLoc(), Record); -} - -void PCHStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { - VisitOverloadExpr(E); - Record.push_back(E->isArrow()); - Record.push_back(E->hasUnresolvedUsing()); - Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : 0); - Writer.AddTypeRef(E->getBaseType(), Record); - Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Code = pch::EXPR_CXX_UNRESOLVED_MEMBER; -} - -void PCHStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { - VisitOverloadExpr(E); - Record.push_back(E->requiresADL()); - Record.push_back(E->isOverloaded()); - Writer.AddDeclRef(E->getNamingClass(), Record); - Code = pch::EXPR_CXX_UNRESOLVED_LOOKUP; -} - -void PCHStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - VisitExpr(E); - Record.push_back(E->getTrait()); - Writer.AddSourceRange(E->getSourceRange(), Record); - Writer.AddTypeRef(E->getQueriedType(), Record); - Code = pch::EXPR_CXX_UNARY_TYPE_TRAIT; -} - -//===----------------------------------------------------------------------===// -// PCHWriter Implementation -//===----------------------------------------------------------------------===// - -unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && - "SwitchCase recorded twice"); - unsigned NextID = SwitchCaseIDs.size(); - SwitchCaseIDs[S] = NextID; - return NextID; -} - -unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && - "SwitchCase hasn't been seen yet"); - return SwitchCaseIDs[S]; -} - -/// \brief Retrieve the ID for the given label statement, which may -/// or may not have been emitted yet. -unsigned PCHWriter::GetLabelID(LabelStmt *S) { - std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S); - if (Pos != LabelIDs.end()) - return Pos->second; - - unsigned NextID = LabelIDs.size(); - LabelIDs[S] = NextID; - return NextID; -} - -/// \brief Write the given substatement or subexpression to the -/// bitstream. -void PCHWriter::WriteSubStmt(Stmt *S) { - RecordData Record; - PCHStmtWriter Writer(*this, Record); - ++NumStatements; - - if (!S) { - Stream.EmitRecord(pch::STMT_NULL_PTR, Record); - return; - } - - // Redirect PCHWriter::AddStmt to collect sub stmts. - llvm::SmallVector<Stmt *, 16> SubStmts; - CollectedStmts = &SubStmts; - - Writer.Code = pch::STMT_NULL_PTR; - Writer.Visit(S); - -#ifndef NDEBUG - if (Writer.Code == pch::STMT_NULL_PTR) { - SourceManager &SrcMgr - = DeclIDs.begin()->first->getASTContext().getSourceManager(); - S->dump(SrcMgr); - assert(0 && "Unhandled sub statement writing PCH file"); - } -#endif - - // Revert PCHWriter::AddStmt. - CollectedStmts = &StmtsToEmit; - - // Write the sub stmts in reverse order, last to first. When reading them back - // we will read them in correct order by "pop"ing them from the Stmts stack. - // This simplifies reading and allows to store a variable number of sub stmts - // without knowing it in advance. - while (!SubStmts.empty()) - WriteSubStmt(SubStmts.pop_back_val()); - - Stream.EmitRecord(Writer.Code, Record); -} - -/// \brief Flush all of the statements that have been added to the -/// queue via AddStmt(). -void PCHWriter::FlushStmts() { - RecordData Record; - - for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { - WriteSubStmt(StmtsToEmit[I]); - - assert(N == StmtsToEmit.size() && - "Substatement writen via AddStmt rather than WriteSubStmt!"); - - // Note that we are at the end of a full expression. Any - // expression records that follow this one are part of a different - // expression. - Stream.EmitRecord(pch::STMT_STOP, Record); - } - - StmtsToEmit.clear(); -} |