diff options
Diffstat (limited to 'lib/Frontend/PCHReader.cpp')
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 286 |
1 files changed, 229 insertions, 57 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 49eb2a0..e659ff0 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -21,6 +21,7 @@ #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" @@ -150,7 +151,10 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, std::pair<llvm::StringRef,llvm::StringRef> Split = llvm::StringRef(PP.getPredefines()).split(PCHInclude.str()); llvm::StringRef Left = Split.first, Right = Split.second; - assert(Left != PP.getPredefines() && "Missing PCH include entry!"); + if (Left == PP.getPredefines()) { + Error("Missing PCH include entry!"); + return true; + } // If the predefines is equal to the joined left and right halves, we're done! if (Left.size() + Right.size() == PCHPredef.size() && @@ -300,8 +304,10 @@ bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, return false; } -void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) { - PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++); +void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI, + unsigned ID) { + PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID); + ++NumHeaderInfos; } void PCHValidator::ReadCounter(unsigned Value) { @@ -321,8 +327,9 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot), - NumStatHits(0), NumStatMisses(0), + TotalNumSelectors(0), MacroDefinitionOffsets(0), + NumPreallocatedPreprocessingEntities(0), + isysroot(isysroot), NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), NumStatementsRead(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), @@ -338,8 +345,9 @@ PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot), - NumStatHits(0), NumStatMisses(0), + TotalNumSelectors(0), MacroDefinitionOffsets(0), + NumPreallocatedPreprocessingEntities(0), + isysroot(isysroot), NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), NumStatementsRead(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), @@ -601,10 +609,8 @@ public: typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait> PCHIdentifierLookupTable; -bool PCHReader::Error(const char *Msg) { - unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg); - Diag(DiagID); - return true; +void PCHReader::Error(const char *Msg) { + Diag(diag::err_fe_pch_malformed) << Msg; } /// \brief Check the contents of the predefines buffer against the @@ -850,17 +856,6 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { return Failure; break; - case pch::SM_HEADER_FILE_INFO: { - HeaderFileInfo HFI; - HFI.isImport = Record[0]; - HFI.DirInfo = Record[1]; - HFI.NumIncludes = Record[2]; - HFI.ControllingMacroID = Record[3]; - if (Listener) - Listener->ReadHeaderFileInfo(HFI); - break; - } - case pch::SM_SLOC_FILE_ENTRY: case pch::SM_SLOC_BUFFER_ENTRY: case pch::SM_SLOC_INSTANTIATION_ENTRY: @@ -910,6 +905,11 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { return Failure; } + if (Record.size() < 8) { + Error("source location entry is incorrect"); + return Failure; + } + FileID FID = SourceMgr.createFileID(File, SourceLocation::getFromRawEncoding(Record[1]), (SrcMgr::CharacteristicKind)Record[2], @@ -918,6 +918,14 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()) .setHasLineDirectives(); + // Reconstruct header-search information for this file. + HeaderFileInfo HFI; + HFI.isImport = Record[4]; + HFI.DirInfo = Record[5]; + HFI.NumIncludes = Record[6]; + HFI.ControllingMacroID = Record[7]; + if (Listener) + Listener->ReadHeaderFileInfo(HFI, File->getUID()); break; } @@ -928,8 +936,12 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { Record.clear(); unsigned RecCode = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); - assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file"); - (void)RecCode; + + if (RecCode != pch::SM_SLOC_BUFFER_BLOB) { + Error("PCH record has invalid code"); + return Failure; + } + llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBuffer(BlobStart, BlobStart + BlobLen - 1, @@ -1038,12 +1050,14 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { MacroInfo *MI = PP->AllocateMacroInfo(Loc); MI->setIsUsed(isUsed); + unsigned NextIndex = 3; if (RecType == pch::PP_MACRO_FUNCTION_LIKE) { // Decode function-like macro info. bool isC99VarArgs = Record[3]; bool isGNUVarArgs = Record[4]; MacroArgs.clear(); unsigned NumArgs = Record[5]; + NextIndex = 6 + NumArgs; for (unsigned i = 0; i != NumArgs; ++i) MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i])); @@ -1061,6 +1075,13 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { // 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; } @@ -1081,6 +1102,64 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { 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; + } } } } @@ -1130,16 +1209,32 @@ void PCHReader::ReadDefinedMacros() { case pch::PP_MACRO_OBJECT_LIKE: case pch::PP_MACRO_FUNCTION_LIKE: - DecodeIdentifierInfo(Record[0]); + DecodeIdentifierInfo(Record[0]); break; case pch::PP_TOKEN: // Ignore tokens. break; + + case pch::PP_MACRO_INSTANTIATION: + case pch::PP_MACRO_DEFINITION: + // Read the macro record. + ReadMacroRecord(Cursor.GetCurrentBitNo()); + break; } } } +MacroDefinition *PCHReader::getMacroDefinition(pch::IdentID ID) { + if (ID == 0 || ID >= MacroDefinitionsLoaded.size()) + return 0; + + if (!MacroDefinitionsLoaded[ID]) + ReadMacroRecord(MacroDefinitionOffsets[ID]); + + return MacroDefinitionsLoaded[ID]; +} + /// \brief If we are loading a relocatable PCH file, and the filename is /// not an absolute path, add the system root to the beginning of the file /// name. @@ -1408,11 +1503,6 @@ PCHReader::ReadPCHBlock() { MaybeAddSystemRootToFilename(OriginalFileName); break; - case pch::COMMENT_RANGES: - Comments = (SourceRange *)BlobStart; - NumComments = BlobLen / sizeof(SourceRange); - break; - case pch::VERSION_CONTROL_BRANCH_REVISION: { const std::string &CurBranch = getClangFullRepositoryVersion(); llvm::StringRef PCHBranch(BlobStart, BlobLen); @@ -1422,6 +1512,19 @@ PCHReader::ReadPCHBlock() { } break; } + + case pch::MACRO_DEFINITION_OFFSETS: + MacroDefinitionOffsets = (const uint32_t *)BlobStart; + if (PP) { + if (!PP->getPreprocessingRecord()) + PP->createPreprocessingRecord(); + PP->getPreprocessingRecord()->SetExternalSource(*this, Record[0]); + } else { + NumPreallocatedPreprocessingEntities = Record[0]; + } + + MacroDefinitionsLoaded.resize(Record[1]); + break; } } Error("premature end of bitstream in PCH file"); @@ -1553,6 +1656,18 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { return Success; } +void PCHReader::setPreprocessor(Preprocessor &pp) { + PP = &pp; + + if (NumPreallocatedPreprocessingEntities) { + if (!PP->getPreprocessingRecord()) + PP->createPreprocessingRecord(); + PP->getPreprocessingRecord()->SetExternalSource(*this, + NumPreallocatedPreprocessingEntities); + NumPreallocatedPreprocessingEntities = 0; + } +} + void PCHReader::InitializeContext(ASTContext &Ctx) { Context = &Ctx; assert(Context && "Passed null context!"); @@ -1584,29 +1699,44 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { Context->setObjCFastEnumerationStateType(GetType(FastEnum)); if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) { QualType FileType = GetType(File); - assert(!FileType.isNull() && "FILE type is NULL"); + 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>(); - assert(Tag && "Invalid FILE type in PCH file"); + 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); - assert(!Jmp_bufType.isNull() && "jmp_bug type is NULL"); + 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>(); - assert(Tag && "Invalid jmp_bug type in PCH file"); + 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); - assert(!Sigjmp_bufType.isNull() && "sigjmp_buf type is NULL"); + 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 { @@ -1799,10 +1929,8 @@ bool PCHReader::ParseLanguageOptions( return false; } -void PCHReader::ReadComments(std::vector<SourceRange> &Comments) { - Comments.resize(NumComments); - std::copy(this->Comments, this->Comments + NumComments, - Comments.begin()); +void PCHReader::ReadPreprocessedEntities() { + ReadDefinedMacros(); } /// \brief Read and return the type at the given offset. @@ -1823,45 +1951,65 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { unsigned Code = DeclsCursor.ReadCode(); switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) { case pch::TYPE_EXT_QUAL: { - assert(Record.size() == 2 && - "Incorrect encoding of extended qualifier type"); + 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: { - assert(Record.size() == 1 && "Incorrect encoding of complex type"); + 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: { - assert(Record.size() == 1 && "Incorrect encoding of pointer type"); + 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: { - assert(Record.size() == 1 && "Incorrect encoding of block pointer type"); + 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: { - assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type"); + 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: { - assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type"); + 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: { - assert(Record.size() == 1 && "Incorrect encoding of member pointer type"); + if (Record.size() != 1) { + 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()); @@ -1957,7 +2105,10 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0]))); case pch::TYPE_TYPEDEF: - assert(Record.size() == 1 && "incorrect encoding of typedef type"); + if (Record.size() != 1) { + Error("incorrect encoding of typedef type"); + return QualType(); + } return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0]))); case pch::TYPE_TYPEOF_EXPR: @@ -1976,15 +2127,24 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { return Context->getDecltypeType(ReadTypeExpr()); case pch::TYPE_RECORD: - assert(Record.size() == 1 && "incorrect encoding of record type"); + if (Record.size() != 1) { + Error("incorrect encoding of record type"); + return QualType(); + } return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0]))); case pch::TYPE_ENUM: - assert(Record.size() == 1 && "incorrect encoding of enum type"); + if (Record.size() != 1) { + Error("incorrect encoding of enum type"); + return QualType(); + } return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0]))); case pch::TYPE_ELABORATED: { - assert(Record.size() == 2 && "incorrect encoding of elaborated type"); + if (Record.size() != 2) { + Error("incorrect encoding of elaborated type"); + return QualType(); + } unsigned Tag = Record[1]; return Context->getElaboratedType(GetType(Record[0]), (ElaboratedType::TagKind) Tag); @@ -2329,8 +2489,12 @@ bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, llvm::SmallVectorImpl<pch::DeclID> &Decls) { assert(DC->hasExternalLexicalStorage() && "DeclContext has no lexical decls in storage"); + uint64_t Offset = DeclContextOffsets[DC].first; - assert(Offset && "DeclContext has no lexical decls in storage"); + if (Offset == 0) { + Error("DeclContext has no lexical decls in storage"); + return true; + } // Keep track of where we are in the stream, then jump back there // after reading this context. @@ -2342,8 +2506,10 @@ bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, RecordData Record; unsigned Code = DeclsCursor.ReadCode(); unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - (void)RecCode; - assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block"); + if (RecCode != pch::DECL_CONTEXT_LEXICAL) { + Error("Expected lexical block"); + return true; + } // Load all of the declaration IDs Decls.clear(); @@ -2357,7 +2523,10 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, assert(DC->hasExternalVisibleStorage() && "DeclContext has no visible decls in storage"); uint64_t Offset = DeclContextOffsets[DC].second; - assert(Offset && "DeclContext has no visible decls in storage"); + if (Offset == 0) { + Error("DeclContext has no visible decls in storage"); + return true; + } // Keep track of where we are in the stream, then jump back there // after reading this context. @@ -2369,8 +2538,11 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, RecordData Record; unsigned Code = DeclsCursor.ReadCode(); unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - (void)RecCode; - assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block"); + if (RecCode != pch::DECL_CONTEXT_VISIBLE) { + Error("Expected visible block"); + return true; + } + if (Record.size() == 0) return false; |