From: Douglas Gregor Date: Tue, 8 Feb 2011 21:58:10 +0000 (+0000) Subject: Split the serialized representation for the detailed preprocessing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4800a5c79023271408af49797e09be32aca93232;p=clang Split the serialized representation for the detailed preprocessing record away from the core processor record. The tangling of these two data structures led to some inefficiencies (e.g., deserializing all of the detailed preprocessing record when we didn't need it, such as while performing code completion) along with some unnecessary ugliness. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125117 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index bb316f0713..5c9a3086cb 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -148,7 +148,10 @@ namespace clang { DECLTYPES_BLOCK_ID, /// \brief The block containing DECL_UPDATES records. - DECL_UPDATES_BLOCK_ID + DECL_UPDATES_BLOCK_ID, + + /// \brief The block containing the detailed preprocessing record. + PREPROCESSOR_DETAIL_BLOCK_ID }; /// \brief Record types that occur within the AST block itself. @@ -383,20 +386,23 @@ namespace clang { /// \brief Describes one token. /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags] - PP_TOKEN = 3, + PP_TOKEN = 3 + }; + /// \brief Record types used within a preprocessor detail block. + enum PreprocessorDetailRecordTypes { /// \brief Describes a macro instantiation within the preprocessing /// record. - PP_MACRO_INSTANTIATION = 4, + PPD_MACRO_INSTANTIATION = 0, /// \brief Describes a macro definition within the preprocessing record. - PP_MACRO_DEFINITION = 5, + PPD_MACRO_DEFINITION = 1, - /// \brief Describes am inclusion directive within the preprocessing + /// \brief Describes an inclusion directive within the preprocessing /// record. - PP_INCLUSION_DIRECTIVE = 6 + PPD_INCLUSION_DIRECTIVE = 2 }; - + /// \defgroup ASTAST AST file AST constants /// /// The constants in this group describe various components of the diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index b9bf5f60b6..ae9820b72f 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -280,9 +280,18 @@ private: /// \brief The offset of the start of the set of defined macros. uint64_t MacroStartOffset; + // === Detailed PreprocessingRecord === + + /// \brief The cursor to the start of the (optional) detailed preprocessing + /// record block. + llvm::BitstreamCursor PreprocessorDetailCursor; + + /// \brief The offset of the start of the preprocessor detail cursor. + uint64_t PreprocessorDetailStartOffset; + /// \brief The number of macro definitions in this file. unsigned LocalNumMacroDefinitions; - + /// \brief Offsets of all of the macro definitions in the preprocessing /// record in the AST file. const uint32_t *MacroDefinitionOffsets; @@ -1175,6 +1184,10 @@ public: /// \brief Reads the macro record located at the given offset. PreprocessedEntity *ReadMacroRecord(PerFileData &F, uint64_t Offset); + /// \brief Reads the preprocessed entity located at the current stream + /// position. + PreprocessedEntity *LoadPreprocessedEntity(PerFileData &F); + /// \brief Note that the identifier is a macro whose record will be loaded /// from the given AST file at the given (file-local) offset. void SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F, diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 0da5ecca4a..17c09254f4 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -47,6 +47,7 @@ class MacroDefinition; class MemorizeStatCalls; class ASTReader; class PreprocessedEntity; +class PreprocessingRecord; class Preprocessor; class Sema; class SourceManager; @@ -311,6 +312,7 @@ private: const Preprocessor &PP, const char* isysroot); void WritePreprocessor(const Preprocessor &PP); + void WritePreprocessorDetail(PreprocessingRecord &PPRec); void WritePragmaDiagnosticMappings(const Diagnostic &Diag); void WriteType(QualType T); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index d2d20bfdbd..0fc62ab96a 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1462,111 +1462,113 @@ PreprocessedEntity *ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) Macro->AddTokenToBody(Tok); break; } + } + } + + return 0; +} - case 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 0; - - if (!PP->getPreprocessingRecord()) { - Error("missing preprocessing record in AST file"); - return 0; - } +PreprocessedEntity *ASTReader::LoadPreprocessedEntity(PerFileData &F) { + assert(PP && "Forgot to set Preprocessor ?"); + unsigned Code = F.PreprocessorDetailCursor.ReadCode(); + switch (Code) { + case llvm::bitc::END_BLOCK: + return 0; + + case llvm::bitc::ENTER_SUBBLOCK: + Error("unexpected subblock record in preprocessor detail block"); + return 0; + + case llvm::bitc::DEFINE_ABBREV: + Error("unexpected abbrevation record in preprocessor detail block"); + return 0; + + default: + break; + } - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) - return PE; - - MacroInstantiation *MI - = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]), - SourceRange(ReadSourceLocation(F, Record[1]), - ReadSourceLocation(F, Record[2])), - getMacroDefinition(Record[4])); - PPRec.SetPreallocatedEntity(Record[0], MI); - return MI; + if (!PP->getPreprocessingRecord()) { + Error("no preprocessing record"); + return 0; + } + + // Read the record. + PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); + const char *BlobStart = 0; + unsigned BlobLen = 0; + RecordData Record; + PreprocessorDetailRecordTypes RecType = + (PreprocessorDetailRecordTypes)F.PreprocessorDetailCursor.ReadRecord( + Code, Record, BlobStart, BlobLen); + switch (RecType) { + case PPD_MACRO_INSTANTIATION: { + if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) + return PE; + + MacroInstantiation *MI + = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]), + SourceRange(ReadSourceLocation(F, Record[1]), + ReadSourceLocation(F, Record[2])), + getMacroDefinition(Record[4])); + PPRec.SetPreallocatedEntity(Record[0], MI); + return MI; + } + + case PPD_MACRO_DEFINITION: { + if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) + return PE; + + if (Record[1] > MacroDefinitionsLoaded.size()) { + Error("out-of-bounds macro definition record"); + return 0; } - - case 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 0; - - if (!PP->getPreprocessingRecord()) { - Error("missing preprocessing record in AST file"); - return 0; - } - - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) - return PE; - - if (Record[1] > MacroDefinitionsLoaded.size()) { - Error("out-of-bounds macro definition record"); - return 0; - } - - // Decode the identifier info and then check again; if the macro is - // still defined and associated with the identifier, - IdentifierInfo *II = DecodeIdentifierInfo(Record[4]); - if (!MacroDefinitionsLoaded[Record[1] - 1]) { - MacroDefinition *MD - = new (PPRec) MacroDefinition(II, - ReadSourceLocation(F, Record[5]), - SourceRange( - ReadSourceLocation(F, Record[2]), - ReadSourceLocation(F, Record[3]))); - - PPRec.SetPreallocatedEntity(Record[0], MD); - MacroDefinitionsLoaded[Record[1] - 1] = MD; - - if (DeserializationListener) - DeserializationListener->MacroDefinitionRead(Record[1], MD); - } - - return MacroDefinitionsLoaded[Record[1] - 1]; + + // Decode the identifier info and then check again; if the macro is + // still defined and associated with the identifier, + IdentifierInfo *II = DecodeIdentifierInfo(Record[4]); + if (!MacroDefinitionsLoaded[Record[1] - 1]) { + MacroDefinition *MD + = new (PPRec) MacroDefinition(II, + ReadSourceLocation(F, Record[5]), + SourceRange( + ReadSourceLocation(F, Record[2]), + ReadSourceLocation(F, Record[3]))); + + PPRec.SetPreallocatedEntity(Record[0], MD); + MacroDefinitionsLoaded[Record[1] - 1] = MD; + + if (DeserializationListener) + DeserializationListener->MacroDefinitionRead(Record[1], MD); } - - case PP_INCLUSION_DIRECTIVE: { - // 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 0; - - if (!PP->getPreprocessingRecord()) { - Error("missing preprocessing record in AST file"); - return 0; - } - - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) - return PE; - - const char *FullFileNameStart = BlobStart + Record[3]; - const FileEntry *File - = PP->getFileManager().getFile(llvm::StringRef(FullFileNameStart, - BlobLen - Record[3])); - - // FIXME: Stable encoding - InclusionDirective::InclusionKind Kind - = static_cast(Record[5]); - InclusionDirective *ID - = new (PPRec) InclusionDirective(PPRec, Kind, - llvm::StringRef(BlobStart, Record[3]), - Record[4], - File, + + return MacroDefinitionsLoaded[Record[1] - 1]; + } + + case PPD_INCLUSION_DIRECTIVE: { + if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0])) + return PE; + + const char *FullFileNameStart = BlobStart + Record[3]; + const FileEntry *File + = PP->getFileManager().getFile(llvm::StringRef(FullFileNameStart, + BlobLen - Record[3])); + + // FIXME: Stable encoding + InclusionDirective::InclusionKind Kind + = static_cast(Record[5]); + InclusionDirective *ID + = new (PPRec) InclusionDirective(PPRec, Kind, + llvm::StringRef(BlobStart, Record[3]), + Record[4], + File, SourceRange(ReadSourceLocation(F, Record[1]), ReadSourceLocation(F, Record[2]))); - PPRec.SetPreallocatedEntity(Record[0], ID); - return ID; - } - } + PPRec.SetPreallocatedEntity(Record[0], ID); + return ID; + } } + Error("invalid offset in preprocessor detail block"); return 0; } @@ -1600,7 +1602,6 @@ void ASTReader::ReadDefinedMacros() { RecordData Record; while (true) { - uint64_t Offset = Cursor.GetCurrentBitNo(); unsigned Code = Cursor.ReadCode(); if (Code == llvm::bitc::END_BLOCK) break; @@ -1636,14 +1637,6 @@ void ASTReader::ReadDefinedMacros() { case PP_TOKEN: // Ignore tokens. break; - - case PP_MACRO_INSTANTIATION: - case PP_MACRO_DEFINITION: - case PP_INCLUSION_DIRECTIVE: - // Read the macro record. - // FIXME: That's a stupid way to do this. We should reuse this cursor. - ReadMacroRecord(F, Offset); - break; } } } @@ -1691,7 +1684,9 @@ MacroDefinition *ASTReader::getMacroDefinition(MacroID ID) { for (unsigned I = 0, N = Chain.size(); I != N; ++I) { PerFileData &F = *Chain[N - I - 1]; if (Index < F.LocalNumMacroDefinitions) { - ReadMacroRecord(F, F.MacroDefinitionOffsets[Index]); + SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor); + F.PreprocessorDetailCursor.JumpToBit(F.MacroDefinitionOffsets[Index]); + LoadPreprocessedEntity(F); break; } Index -= F.LocalNumMacroDefinitions; @@ -1785,6 +1780,18 @@ ASTReader::ReadASTBlock(PerFileData &F) { F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo(); break; + case PREPROCESSOR_DETAIL_BLOCK_ID: + F.PreprocessorDetailCursor = Stream; + if (Stream.SkipBlock() || + ReadBlockAbbrevs(F.PreprocessorDetailCursor, + PREPROCESSOR_DETAIL_BLOCK_ID)) { + Error("malformed preprocessor detail record in AST file"); + return Failure; + } + F.PreprocessorDetailStartOffset + = F.PreprocessorDetailCursor.GetCurrentBitNo(); + break; + case SOURCE_MANAGER_BLOCK_ID: switch (ReadSourceManagerBlock(F)) { case Success: @@ -2656,7 +2663,15 @@ bool ASTReader::ParseLanguageOptions( } void ASTReader::ReadPreprocessedEntities() { - ReadDefinedMacros(); + for (unsigned I = 0, N = Chain.size(); I != N; ++I) { + PerFileData &F = *Chain[I]; + if (!F.PreprocessorDetailCursor.getBitStreamReader()) + continue; + + SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor); + F.PreprocessorDetailCursor.JumpToBit(F.PreprocessorDetailStartOffset); + while (LoadPreprocessedEntity(F)) { } + } } PreprocessedEntity *ASTReader::ReadPreprocessedEntity(uint64_t Offset) { @@ -2675,7 +2690,11 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(uint64_t Offset) { return 0; } - return ReadMacroRecord(*F, Offset); + // Keep track of where we are in the stream, then jump back there + // after reading this entity. + SavedStreamPosition SavedPosition(F->PreprocessorDetailCursor); + F->PreprocessorDetailCursor.JumpToBit(Offset); + return LoadPreprocessedEntity(*F); } void ASTReader::ReadPragmaDiagnosticMappings(Diagnostic &Diag) { diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 14604a2c2f..fdd5800e9c 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -752,9 +752,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(PP_MACRO_OBJECT_LIKE); RECORD(PP_MACRO_FUNCTION_LIKE); RECORD(PP_TOKEN); - RECORD(PP_MACRO_INSTANTIATION); - RECORD(PP_MACRO_DEFINITION); - RECORD(PP_INCLUSION_DIRECTIVE); // Decls and Types block. BLOCK(DECLTYPES_BLOCK); @@ -850,6 +847,11 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_INDIRECTFIELD); RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK); + BLOCK(PREPROCESSOR_DETAIL_BLOCK); + RECORD(PPD_MACRO_INSTANTIATION); + RECORD(PPD_MACRO_DEFINITION); + RECORD(PPD_INCLUSION_DIRECTIVE); + // Statements and Exprs can occur in the Decls and Types block. AddStmtsExprs(Stream, Record); #undef RECORD @@ -1409,21 +1411,8 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { // 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(); - unsigned InclusionAbbrev = 0; - if (PPRec) { - using namespace llvm; - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); - Abbrev->Add(BitCodeAbbrevOp(PP_INCLUSION_DIRECTIVE)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // start location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // end location - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - InclusionAbbrev = Stream.EmitAbbrev(Abbrev); - } + // FIXME: If we are chaining, don't visit all of the macros! 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 @@ -1493,82 +1482,109 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP) { } ++NumMacros; } + Stream.ExitBlock(); + + if (PPRec) + WritePreprocessorDetail(*PPRec); +} + +void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { + if (PPRec.begin(Chain) == PPRec.end(Chain)) + return; + + // Enter the preprocessor block. + Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3); // If the preprocessor has a preprocessing record, emit it. unsigned NumPreprocessingRecords = 0; - if (PPRec) { - unsigned IndexBase = Chain ? PPRec->getNumPreallocatedEntities() : 0; - for (PreprocessingRecord::iterator E = PPRec->begin(Chain), - EEnd = PPRec->end(Chain); - E != EEnd; ++E) { - Record.clear(); + using namespace llvm; + + // Set up the abbreviation for + unsigned InclusionAbbrev = 0; + { + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // start location + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // end location + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + InclusionAbbrev = Stream.EmitAbbrev(Abbrev); + } + + unsigned IndexBase = Chain ? PPRec.getNumPreallocatedEntities() : 0; + RecordData Record; + for (PreprocessingRecord::iterator E = PPRec.begin(Chain), + EEnd = PPRec.end(Chain); + E != EEnd; ++E) { + Record.clear(); - if (MacroDefinition *MD = dyn_cast(*E)) { - // Record this macro definition's location. - MacroID ID = getMacroDefinitionID(MD); - - // Don't write the macro definition if it is from another AST file. - if (ID < FirstMacroID) - continue; - - // Notify the serialization listener that we're serializing this entity. - if (SerializationListener) - SerializationListener->SerializedPreprocessedEntity(*E, - Stream.GetCurrentBitNo()); - - unsigned Position = ID - FirstMacroID; - if (Position != MacroDefinitionOffsets.size()) { - if (Position > MacroDefinitionOffsets.size()) - MacroDefinitionOffsets.resize(Position + 1); - - MacroDefinitionOffsets[Position] = Stream.GetCurrentBitNo(); - } else - MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo()); - - Record.push_back(IndexBase + 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(PP_MACRO_DEFINITION, Record); + if (MacroDefinition *MD = dyn_cast(*E)) { + // Record this macro definition's location. + MacroID ID = getMacroDefinitionID(MD); + + // Don't write the macro definition if it is from another AST file. + if (ID < FirstMacroID) continue; - } - + // Notify the serialization listener that we're serializing this entity. if (SerializationListener) SerializationListener->SerializedPreprocessedEntity(*E, - Stream.GetCurrentBitNo()); - - if (MacroInstantiation *MI = dyn_cast(*E)) { - Record.push_back(IndexBase + NumPreprocessingRecords++); - AddSourceLocation(MI->getSourceRange().getBegin(), Record); - AddSourceLocation(MI->getSourceRange().getEnd(), Record); - AddIdentifierRef(MI->getName(), Record); - Record.push_back(getMacroDefinitionID(MI->getDefinition())); - Stream.EmitRecord(PP_MACRO_INSTANTIATION, Record); - continue; - } + Stream.GetCurrentBitNo()); - if (InclusionDirective *ID = dyn_cast(*E)) { - Record.push_back(PP_INCLUSION_DIRECTIVE); - Record.push_back(IndexBase + NumPreprocessingRecords++); - AddSourceLocation(ID->getSourceRange().getBegin(), Record); - AddSourceLocation(ID->getSourceRange().getEnd(), Record); - Record.push_back(ID->getFileName().size()); - Record.push_back(ID->wasInQuotes()); - Record.push_back(static_cast(ID->getKind())); - llvm::SmallString<64> Buffer; - Buffer += ID->getFileName(); - Buffer += ID->getFile()->getName(); - Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); - continue; - } + unsigned Position = ID - FirstMacroID; + if (Position != MacroDefinitionOffsets.size()) { + if (Position > MacroDefinitionOffsets.size()) + MacroDefinitionOffsets.resize(Position + 1); + + MacroDefinitionOffsets[Position] = Stream.GetCurrentBitNo(); + } else + MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo()); - llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter"); + Record.push_back(IndexBase + 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(PPD_MACRO_DEFINITION, Record); + continue; } - } + // Notify the serialization listener that we're serializing this entity. + if (SerializationListener) + SerializationListener->SerializedPreprocessedEntity(*E, + Stream.GetCurrentBitNo()); + + if (MacroInstantiation *MI = dyn_cast(*E)) { + Record.push_back(IndexBase + NumPreprocessingRecords++); + AddSourceLocation(MI->getSourceRange().getBegin(), Record); + AddSourceLocation(MI->getSourceRange().getEnd(), Record); + AddIdentifierRef(MI->getName(), Record); + Record.push_back(getMacroDefinitionID(MI->getDefinition())); + Stream.EmitRecord(PPD_MACRO_INSTANTIATION, Record); + continue; + } + + if (InclusionDirective *ID = dyn_cast(*E)) { + Record.push_back(PPD_INCLUSION_DIRECTIVE); + Record.push_back(IndexBase + NumPreprocessingRecords++); + AddSourceLocation(ID->getSourceRange().getBegin(), Record); + AddSourceLocation(ID->getSourceRange().getEnd(), Record); + Record.push_back(ID->getFileName().size()); + Record.push_back(ID->wasInQuotes()); + Record.push_back(static_cast(ID->getKind())); + llvm::SmallString<64> Buffer; + Buffer += ID->getFileName(); + Buffer += ID->getFile()->getName(); + Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); + continue; + } + + llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter"); + } Stream.ExitBlock(); // Write the offsets table for the preprocessing record.