diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp | 621 |
1 files changed, 497 insertions, 124 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp b/contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp index 88e9b9d..00aee49 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp @@ -13,6 +13,7 @@ #include "clang/Frontend/PCHReader.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/PCHDeserializationListener.h" #include "clang/Frontend/Utils.h" #include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere #include "clang/AST/ASTConsumer.h" @@ -93,7 +94,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks); PARSE_LANGOPT_BENIGN(EmitAllDecls); PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno); - PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking); + 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 @@ -124,6 +125,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { 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 @@ -139,8 +141,86 @@ bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) { return true; } -bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, - FileID PCHBufferID, +struct EmptyStringRef { + bool operator ()(llvm::StringRef r) const { return r.empty(); } +}; +struct EmptyBlock { + bool operator ()(const PCHPredefinesBlock &r) const { return r.Data.empty(); } +}; + +static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L, + PCHPredefinesBlocks R) { + // First, sum up the lengths. + unsigned LL = 0, RL = 0; + for (unsigned I = 0, N = L.size(); I != N; ++I) { + LL += L[I].size(); + } + for (unsigned I = 0, N = R.size(); I != N; ++I) { + RL += R[I].Data.size(); + } + if (LL != RL) + return false; + if (LL == 0 && RL == 0) + return true; + + // Kick out empty parts, they confuse the algorithm below. + L.erase(std::remove_if(L.begin(), L.end(), EmptyStringRef()), L.end()); + R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end()); + + // Do it the hard way. At this point, both vectors must be non-empty. + llvm::StringRef LR = L[0], RR = R[0].Data; + unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size(); + for (;;) { + // Compare the current pieces. + if (LR.size() == RR.size()) { + // If they're the same length, it's pretty easy. + if (LR != RR) + return false; + // Both pieces are done, advance. + ++LI; + ++RI; + // If either string is done, they're both done, since they're the same + // length. + if (LI == LN) { + assert(RI == RN && "Strings not the same length after all?"); + return true; + } + LR = L[LI]; + RR = R[RI].Data; + } else if (LR.size() < RR.size()) { + // Right piece is longer. + if (!RR.startswith(LR)) + return false; + ++LI; + assert(LI != LN && "Strings not the same length after all?"); + RR = RR.substr(LR.size()); + LR = L[LI]; + } else { + // Left piece is longer. + if (!LR.startswith(RR)) + return false; + ++RI; + assert(RI != RN && "Strings not the same length after all?"); + LR = LR.substr(RR.size()); + RR = R[RI].Data; + } + } +} + +static std::pair<FileID, llvm::StringRef::size_type> +FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) { + std::pair<FileID, llvm::StringRef::size_type> Res; + for (unsigned I = 0, N = Buffers.size(); I != N; ++I) { + Res.second = Buffers[I].Data.find(MacroDef); + if (Res.second != llvm::StringRef::npos) { + Res.first = Buffers[I].BufferID; + break; + } + } + return Res; +} + +bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, llvm::StringRef OriginalFileName, std::string &SuggestedPredefines) { // We are in the context of an implicit include, so the predefines buffer will @@ -159,9 +239,15 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, return true; } - // If the predefines is equal to the joined left and right halves, we're done! - if (Left.size() + Right.size() == PCHPredef.size() && - PCHPredef.startswith(Left) && PCHPredef.endswith(Right)) + // 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(); @@ -169,7 +255,8 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, // 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; - PCHPredef.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + 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); @@ -234,10 +321,12 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, << MacroName; // Show the definition of this macro within the PCH file. - llvm::StringRef::size_type Offset = PCHPredef.find(Missing); - assert(Offset != llvm::StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID) - .getFileLocWithOffset(Offset); + 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; @@ -255,10 +344,12 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, } // Show the definition of this macro within the PCH file. - llvm::StringRef::size_type Offset = PCHPredef.find(Missing); - assert(Offset != llvm::StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID) - .getFileLocWithOffset(Offset); + 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); } @@ -323,10 +414,10 @@ void PCHValidator::ReadCounter(unsigned Value) { PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot) - : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()), - FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), - SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0), - IdentifierTableData(0), IdentifierLookupTable(0), + : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), + SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), + Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), + StatCache(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), @@ -342,8 +433,8 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, Diagnostic &Diags, const char *isysroot) - : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags), - SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0), + : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), + Diags(Diags), SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), @@ -360,14 +451,6 @@ PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, PCHReader::~PCHReader() {} -Expr *PCHReader::ReadDeclExpr() { - return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor)); -} - -Expr *PCHReader::ReadTypeExpr() { - return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor)); -} - namespace { class PCHMethodPoolLookupTrait { @@ -616,27 +699,18 @@ void PCHReader::Error(const char *Msg) { Diag(diag::err_fe_pch_malformed) << Msg; } -/// \brief Check the contents of the predefines buffer against the -/// contents of the predefines buffer used to build the PCH file. -/// -/// The contents of the two predefines buffers should be the same. If -/// not, then some command-line option changed the preprocessor state -/// and we must reject the PCH file. -/// -/// \param PCHPredef The start of the predefines buffer in the PCH -/// file. -/// -/// \param PCHPredefLen The length of the predefines buffer in the PCH -/// file. +/// \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. /// -/// \param PCHBufferID The FileID for the PCH predefines buffer. +/// 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::CheckPredefinesBuffer(llvm::StringRef PCHPredef, - FileID PCHBufferID) { +bool PCHReader::CheckPredefinesBuffers() { if (Listener) - return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID, + return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers, ActualOriginalFileName, SuggestedPredefines); return false; @@ -667,16 +741,17 @@ bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) { // Parse the line entries std::vector<LineEntry> Entries; while (Idx < Record.size()) { - int FID = FileIDs[Record[Idx++]]; + 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 = Record[Idx++]; + int FilenameID = FileIDs[Record[Idx++]]; SrcMgr::CharacteristicKind FileKind = (SrcMgr::CharacteristicKind)Record[Idx++]; unsigned IncludeOffset = Record[Idx++]; @@ -964,9 +1039,11 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); if (strcmp(Name, "<built-in>") == 0) { - PCHPredefinesBufferID = BufferID; - PCHPredefines = BlobStart; - PCHPredefinesLen = BlobLen - 1; + PCHPredefinesBlock Block = { + BufferID, + llvm::StringRef(BlobStart, BlobLen - 1) + }; + PCHPredefinesBuffers.push_back(Block); } break; @@ -1512,6 +1589,22 @@ PCHReader::ReadPCHBlock() { ExtVectorDecls.swap(Record); break; + case pch::VTABLE_USES: + if (!VTableUses.empty()) { + Error("duplicate VTABLE_USES record in PCH file"); + return Failure; + } + VTableUses.swap(Record); + break; + + case pch::DYNAMIC_CLASSES: + if (!DynamicClasses.empty()) { + Error("duplicate DYNAMIC_CLASSES record in PCH file"); + return Failure; + } + DynamicClasses.swap(Record); + break; + case pch::ORIGINAL_FILE_NAME: ActualOriginalFileName.assign(BlobStart, BlobLen); OriginalFileName = ActualOriginalFileName; @@ -1626,8 +1719,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { } // Check the predefines buffer. - if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen), - PCHPredefinesBufferID)) + if (CheckPredefinesBuffers()) return IgnorePCH; if (PP) { @@ -1693,7 +1785,7 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { PP->setExternalSource(this); // Load the translation unit declaration - ReadDeclRecord(DeclOffsets[0], 0); + GetTranslationUnitDecl(); // Load the special types. Context->setBuiltinVaListType( @@ -1776,6 +1868,9 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { 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 @@ -1915,7 +2010,8 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(Blocks); PARSE_LANGOPT(EmitAllDecls); PARSE_LANGOPT(MathErrno); - PARSE_LANGOPT(OverflowChecking); + LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy) + Record[Idx++]); PARSE_LANGOPT(HeinousExtensions); PARSE_LANGOPT(Optimize); PARSE_LANGOPT(OptimizeSize); @@ -1926,13 +2022,10 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(AccessControl); PARSE_LANGOPT(CharIsSigned); PARSE_LANGOPT(ShortWChar); - LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]); - ++Idx; - LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]); - ++Idx; + LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]); + LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]); LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode) - Record[Idx]); - ++Idx; + Record[Idx++]); PARSE_LANGOPT(InstantiationDepth); PARSE_LANGOPT(OpenCL); PARSE_LANGOPT(CatchUndefined); @@ -1959,6 +2052,8 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { // after reading this type. SavedStreamPosition SavedPosition(DeclsCursor); + ReadingKindTracker ReadingKind(Read_Type, *this); + // Note that we are loading a type record. LoadingTypeOrDecl Loading(*this); @@ -2022,7 +2117,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { } case pch::TYPE_MEMBER_POINTER: { - if (Record.size() != 1) { + if (Record.size() != 2) { Error("Incorrect encoding of member pointer type"); return QualType(); } @@ -2054,26 +2149,26 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { unsigned IndexTypeQuals = Record[2]; SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); - return Context->getVariableArrayType(ElementType, ReadTypeExpr(), + return Context->getVariableArrayType(ElementType, ReadExpr(), ASM, IndexTypeQuals, SourceRange(LBLoc, RBLoc)); } case pch::TYPE_VECTOR: { - if (Record.size() != 4) { + if (Record.size() != 3) { Error("incorrect encoding of vector type in PCH file"); return QualType(); } QualType ElementType = GetType(Record[0]); unsigned NumElements = Record[1]; - bool AltiVec = Record[2]; - bool Pixel = Record[3]; - return Context->getVectorType(ElementType, NumElements, AltiVec, Pixel); + unsigned AltiVecSpec = Record[2]; + return Context->getVectorType(ElementType, NumElements, + (VectorType::AltiVecSpecific)AltiVecSpec); } case pch::TYPE_EXT_VECTOR: { - if (Record.size() != 4) { + if (Record.size() != 3) { Error("incorrect encoding of extended vector type in PCH file"); return QualType(); } @@ -2123,15 +2218,18 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { return Context->getTypeDeclType( cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0]))); - case pch::TYPE_TYPEDEF: - if (Record.size() != 1) { + case pch::TYPE_TYPEDEF: { + if (Record.size() != 2) { Error("incorrect encoding of typedef type"); return QualType(); } - return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0]))); + 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(ReadTypeExpr()); + return Context->getTypeOfExprType(ReadExpr()); case pch::TYPE_TYPEOF: { if (Record.size() != 1) { @@ -2143,32 +2241,36 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { } case pch::TYPE_DECLTYPE: - return Context->getDecltypeType(ReadTypeExpr()); + return Context->getDecltypeType(ReadExpr()); - case pch::TYPE_RECORD: - if (Record.size() != 1) { + case pch::TYPE_RECORD: { + if (Record.size() != 2) { Error("incorrect encoding of record type"); return QualType(); } - return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0]))); + 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() != 1) { + case pch::TYPE_ENUM: { + if (Record.size() != 2) { Error("incorrect encoding of enum type"); return QualType(); } - return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0]))); + bool IsDependent = Record[0]; + QualType T = Context->getEnumType(cast<EnumDecl>(GetDecl(Record[1]))); + T->Dependent = IsDependent; + return T; + } case pch::TYPE_ELABORATED: { - if (Record.size() != 2) { - Error("incorrect encoding of elaborated type"); - return QualType(); - } - unsigned Tag = Record[1]; - // FIXME: Deserialize the qualifier (C++ only) - return Context->getElaboratedType((ElaboratedTypeKeyword) Tag, - /* NNS */ 0, - GetType(Record[0])); + 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: { @@ -2205,7 +2307,77 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { case pch::TYPE_INJECTED_CLASS_NAME: { CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0])); QualType TST = GetType(Record[1]); // probably derivable - return Context->getInjectedClassNameType(D, TST); + // FIXME: ASTContext::getInjectedClassNameType is not currently suitable + // for PCH reading, too much interdependencies. + return + QualType(new (*Context, TypeAlignment) InjectedClassNameType(D, TST), 0); + } + + case pch::TYPE_TEMPLATE_TYPE_PARM: { + unsigned Idx = 0; + unsigned Depth = Record[Idx++]; + unsigned Index = Record[Idx++]; + bool Pack = Record[Idx++]; + IdentifierInfo *Name = GetIdentifierInfo(Record, Idx); + return Context->getTemplateTypeParmType(Depth, Index, Pack, Name); + } + + case pch::TYPE_DEPENDENT_NAME: { + unsigned Idx = 0; + ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); + const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); + QualType Canon = GetType(Record[Idx++]); + return Context->getDependentNameType(Keyword, NNS, Name, Canon); + } + + case pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: { + unsigned Idx = 0; + ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); + const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); + unsigned NumArgs = Record[Idx++]; + llvm::SmallVector<TemplateArgument, 8> Args; + Args.reserve(NumArgs); + while (NumArgs--) + Args.push_back(ReadTemplateArgument(Record, Idx)); + return Context->getDependentTemplateSpecializationType(Keyword, NNS, Name, + Args.size(), Args.data()); + } + + case pch::TYPE_DEPENDENT_SIZED_ARRAY: { + unsigned Idx = 0; + + // ArrayType + QualType ElementType = GetType(Record[Idx++]); + ArrayType::ArraySizeModifier ASM + = (ArrayType::ArraySizeModifier)Record[Idx++]; + unsigned IndexTypeQuals = Record[Idx++]; + + // DependentSizedArrayType + Expr *NumElts = ReadExpr(); + SourceRange Brackets = ReadSourceRange(Record, Idx); + + return Context->getDependentSizedArrayType(ElementType, NumElts, ASM, + IndexTypeQuals, Brackets); + } + + case pch::TYPE_TEMPLATE_SPECIALIZATION: { + unsigned Idx = 0; + bool IsDependent = Record[Idx++]; + TemplateName Name = ReadTemplateName(Record, Idx); + llvm::SmallVector<TemplateArgument, 8> Args; + ReadTemplateArgumentList(Args, Record, Idx); + QualType Canon = GetType(Record[Idx++]); + QualType T; + if (Canon.isNull()) + T = Context->getCanonicalTemplateSpecializationType(Name, Args.data(), + Args.size()); + else + T = Context->getTemplateSpecializationType(Name, Args.data(), + Args.size(), Canon); + T->Dependent = IsDependent; + return T; } } // Suppress a GCC warning @@ -2272,7 +2444,7 @@ void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); if (Record[Idx++]) - TL.setSizeExpr(Reader.ReadDeclExpr()); + TL.setSizeExpr(Reader.ReadExpr()); else TL.setSizeExpr(0); } @@ -2367,6 +2539,18 @@ void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } +void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); + TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + TL.setArgLocInfo(I, + Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), + Record, Idx)); +} void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } @@ -2443,8 +2627,12 @@ QualType PCHReader::GetType(pch::TypeID ID) { Index -= pch::NUM_PREDEF_TYPE_IDS; //assert(Index < TypesLoaded.size() && "Type index out-of-range"); - if (TypesLoaded[Index].isNull()) + if (TypesLoaded[Index].isNull()) { TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]); + TypesLoaded[Index]->setFromPCH(); + if (DeserializationListener) + DeserializationListener->TypeRead(ID, TypesLoaded[Index]); + } return TypesLoaded[Index].withFastQualifiers(FastQuals); } @@ -2455,16 +2643,13 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, unsigned &Index) { switch (Kind) { case TemplateArgument::Expression: - return ReadDeclExpr(); + return ReadExpr(); case TemplateArgument::Type: return GetTypeSourceInfo(Record, Index); case TemplateArgument::Template: { - SourceLocation - QualStart = SourceLocation::getFromRawEncoding(Record[Index++]), - QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]), - TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]); - return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd), - TemplateNameLoc); + SourceRange QualifierRange = ReadSourceRange(Record, Index); + SourceLocation TemplateNameLoc = ReadSourceLocation(Record, Index); + return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc); } case TemplateArgument::Null: case TemplateArgument::Integral: @@ -2476,6 +2661,32 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, return TemplateArgumentLocInfo(); } +TemplateArgumentLoc +PCHReader::ReadTemplateArgumentLoc(const RecordData &Record, unsigned &Index) { + TemplateArgument Arg = ReadTemplateArgument(Record, Index); + + if (Arg.getKind() == TemplateArgument::Expression) { + if (Record[Index++]) // bool InfoHasSameExpr. + return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr())); + } + return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(), + Record, Index)); +} + +Decl *PCHReader::GetExternalDecl(uint32_t ID) { + return GetDecl(ID); +} + +TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() { + if (!DeclsLoaded[0]) { + ReadDeclRecord(DeclOffsets[0], 0); + if (DeserializationListener) + DeserializationListener->DeclRead(0, DeclsLoaded[0]); + } + + return cast<TranslationUnitDecl>(DeclsLoaded[0]); +} + Decl *PCHReader::GetDecl(pch::DeclID ID) { if (ID == 0) return 0; @@ -2486,8 +2697,11 @@ Decl *PCHReader::GetDecl(pch::DeclID ID) { } unsigned Index = ID - 1; - if (!DeclsLoaded[Index]) + if (!DeclsLoaded[Index]) { ReadDeclRecord(DeclOffsets[Index], Index); + if (DeserializationListener) + DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); + } return DeclsLoaded[Index]; } @@ -2497,15 +2711,15 @@ Decl *PCHReader::GetDecl(pch::DeclID ID) { /// 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::GetDeclStmt(uint64_t Offset) { +Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) { // Since we know tha this statement is part of a decl, make sure to use the // decl cursor to read it. DeclsCursor.JumpToBit(Offset); - return ReadStmt(DeclsCursor); + return ReadStmtFromStream(DeclsCursor); } -bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, - llvm::SmallVectorImpl<pch::DeclID> &Decls) { +bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Decls) { assert(DC->hasExternalLexicalStorage() && "DeclContext has no lexical decls in storage"); @@ -2531,20 +2745,22 @@ bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, } // Load all of the declaration IDs - Decls.clear(); - Decls.insert(Decls.end(), Record.begin(), Record.end()); + for (RecordData::iterator I = Record.begin(), E = Record.end(); I != E; ++I) + Decls.push_back(GetDecl(*I)); ++NumLexicalDeclContextsRead; return false; } -bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, - llvm::SmallVectorImpl<VisibleDeclaration> &Decls) { +DeclContext::lookup_result +PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) { assert(DC->hasExternalVisibleStorage() && "DeclContext has no visible decls in storage"); uint64_t Offset = DeclContextOffsets[DC].second; if (Offset == 0) { Error("DeclContext has no visible decls in storage"); - return true; + return DeclContext::lookup_result(DeclContext::lookup_iterator(), + DeclContext::lookup_iterator()); } // Keep track of where we are in the stream, then jump back there @@ -2559,13 +2775,16 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); if (RecCode != pch::DECL_CONTEXT_VISIBLE) { Error("Expected visible block"); - return true; + return DeclContext::lookup_result(DeclContext::lookup_iterator(), + DeclContext::lookup_iterator()); } - if (Record.size() == 0) - return false; - - Decls.clear(); + llvm::SmallVector<VisibleDeclaration, 64> Decls; + if (Record.empty()) { + SetExternalVisibleDecls(DC, Decls); + return DeclContext::lookup_result(DeclContext::lookup_iterator(), + DeclContext::lookup_iterator()); + } unsigned Idx = 0; while (Idx < Record.size()) { @@ -2580,7 +2799,18 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, } ++NumVisibleDeclContextsRead; - return false; + + SetExternalVisibleDecls(DC, Decls); + return const_cast<DeclContext*>(DC)->lookup(Name); +} + +void PCHReader::PassInterestingDeclsToConsumer() { + assert(Consumer); + while (!InterestingDecls.empty()) { + DeclGroupRef DG(InterestingDecls.front()); + InterestingDecls.pop_front(); + Consumer->HandleTopLevelDecl(DG); + } } void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { @@ -2590,15 +2820,12 @@ void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { return; for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) { - // Force deserialization of this decl, which will cause it to be passed to - // the consumer (or queued). + // Force deserialization of this decl, which will cause it to be queued for + // passing to the consumer. GetDecl(ExternalDefinitions[I]); } - for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) { - DeclGroupRef DG(InterestingDecls[I]); - Consumer->HandleTopLevelDecl(DG); - } + PassInterestingDeclsToConsumer(); } void PCHReader::PrintStats() { @@ -2708,6 +2935,26 @@ void PCHReader::InitializeSema(Sema &S) { for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) SemaObj->ExtVectorDecls.push_back( cast<TypedefDecl>(GetDecl(ExtVectorDecls[I]))); + + // FIXME: Do VTable uses and dynamic classes deserialize too much ? + // Can we cut them down before writing them ? + + // If there were any VTable uses, deserialize the information and add it + // to Sema's vector and map of VTable uses. + unsigned Idx = 0; + for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) { + CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++])); + SourceLocation Loc = ReadSourceLocation(VTableUses, Idx); + bool DefinitionRequired = VTableUses[Idx++]; + SemaObj->VTableUses.push_back(std::make_pair(Class, Loc)); + SemaObj->VTablesUsed[Class] = DefinitionRequired; + } + + // If there were any dynamic classes declarations, deserialize them + // and add them to Sema's vector of such declarations. + for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) + SemaObj->DynamicClasses.push_back( + cast<CXXRecordDecl>(GetDecl(DynamicClasses[I]))); } IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) { @@ -2853,11 +3100,11 @@ Selector PCHReader::DecodeSelector(unsigned ID) { return SelectorsLoaded[Index]; } -Selector PCHReader::GetSelector(uint32_t ID) { +Selector PCHReader::GetExternalSelector(uint32_t ID) { return DecodeSelector(ID); } -uint32_t PCHReader::GetNumKnownSelectors() { +uint32_t PCHReader::GetNumExternalSelectors() { return TotalNumSelectors + 1; } @@ -2901,6 +3148,126 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { return DeclarationName(); } +TemplateName +PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) { + TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; + switch (Kind) { + case TemplateName::Template: + return TemplateName(cast_or_null<TemplateDecl>(GetDecl(Record[Idx++]))); + + case TemplateName::OverloadedTemplate: { + unsigned size = Record[Idx++]; + UnresolvedSet<8> Decls; + while (size--) + Decls.addDecl(cast<NamedDecl>(GetDecl(Record[Idx++]))); + + return Context->getOverloadedTemplateName(Decls.begin(), Decls.end()); + } + + case TemplateName::QualifiedTemplate: { + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); + bool hasTemplKeyword = Record[Idx++]; + TemplateDecl *Template = cast<TemplateDecl>(GetDecl(Record[Idx++])); + return Context->getQualifiedTemplateName(NNS, hasTemplKeyword, Template); + } + + case TemplateName::DependentTemplate: { + NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); + if (Record[Idx++]) // isIdentifier + return Context->getDependentTemplateName(NNS, + GetIdentifierInfo(Record, Idx)); + return Context->getDependentTemplateName(NNS, + (OverloadedOperatorKind)Record[Idx++]); + } + } + + assert(0 && "Unhandled template name kind!"); + return TemplateName(); +} + +TemplateArgument +PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) { + switch ((TemplateArgument::ArgKind)Record[Idx++]) { + case TemplateArgument::Null: + return TemplateArgument(); + case TemplateArgument::Type: + return TemplateArgument(GetType(Record[Idx++])); + case TemplateArgument::Declaration: + return TemplateArgument(GetDecl(Record[Idx++])); + case TemplateArgument::Integral: { + llvm::APSInt Value = ReadAPSInt(Record, Idx); + QualType T = GetType(Record[Idx++]); + return TemplateArgument(Value, T); + } + case TemplateArgument::Template: + return TemplateArgument(ReadTemplateName(Record, Idx)); + case TemplateArgument::Expression: + return TemplateArgument(ReadExpr()); + case TemplateArgument::Pack: { + unsigned NumArgs = Record[Idx++]; + llvm::SmallVector<TemplateArgument, 8> Args; + Args.reserve(NumArgs); + while (NumArgs--) + Args.push_back(ReadTemplateArgument(Record, Idx)); + TemplateArgument TemplArg; + TemplArg.setArgumentPack(Args.data(), Args.size(), /*CopyArgs=*/true); + return TemplArg; + } + } + + assert(0 && "Unhandled template argument kind!"); + return TemplateArgument(); +} + +TemplateParameterList * +PCHReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) { + SourceLocation TemplateLoc = ReadSourceLocation(Record, Idx); + SourceLocation LAngleLoc = ReadSourceLocation(Record, Idx); + SourceLocation RAngleLoc = ReadSourceLocation(Record, Idx); + + unsigned NumParams = Record[Idx++]; + llvm::SmallVector<NamedDecl *, 16> Params; + Params.reserve(NumParams); + while (NumParams--) + Params.push_back(cast<NamedDecl>(GetDecl(Record[Idx++]))); + + TemplateParameterList* TemplateParams = + TemplateParameterList::Create(*Context, TemplateLoc, LAngleLoc, + Params.data(), Params.size(), RAngleLoc); + return TemplateParams; +} + +void +PCHReader:: +ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs, + const RecordData &Record, unsigned &Idx) { + unsigned NumTemplateArgs = Record[Idx++]; + TemplArgs.reserve(NumTemplateArgs); + while (NumTemplateArgs--) + TemplArgs.push_back(ReadTemplateArgument(Record, Idx)); +} + +/// \brief Read a UnresolvedSet structure. +void PCHReader::ReadUnresolvedSet(UnresolvedSetImpl &Set, + const RecordData &Record, unsigned &Idx) { + unsigned NumDecls = Record[Idx++]; + while (NumDecls--) { + NamedDecl *D = cast<NamedDecl>(GetDecl(Record[Idx++])); + AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; + Set.addDecl(D, AS); + } +} + +CXXBaseSpecifier +PCHReader::ReadCXXBaseSpecifier(const RecordData &Record, unsigned &Idx) { + bool isVirtual = static_cast<bool>(Record[Idx++]); + bool isBaseOfClass = static_cast<bool>(Record[Idx++]); + AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]); + QualType T = GetType(Record[Idx++]); + SourceRange Range = ReadSourceRange(Record, Idx); + return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, T); +} + NestedNameSpecifier * PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { unsigned N = Record[Idx++]; @@ -2934,16 +3301,17 @@ PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { // No associated value, and there can't be a prefix. break; } - Prev = NNS; } + Prev = NNS; } return NNS; } SourceRange PCHReader::ReadSourceRange(const RecordData &Record, unsigned &Idx) { - return SourceRange(SourceLocation::getFromRawEncoding(Record[Idx++]), - SourceLocation::getFromRawEncoding(Record[Idx++])); + SourceLocation beg = SourceLocation::getFromRawEncoding(Record[Idx++]); + SourceLocation end = SourceLocation::getFromRawEncoding(Record[Idx++]); + return SourceRange(beg, end); } /// \brief Read an integral value @@ -3090,6 +3458,11 @@ PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() { true); Reader.PendingIdentifierInfos.pop_front(); } + + // We are not in recursive loading, so it's safe to pass the "interesting" + // decls to the consumer. + if (Reader.Consumer) + Reader.PassInterestingDeclsToConsumer(); } Reader.CurrentlyLoadingTypeOrDecl = Parent; |