diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1588,13 +1588,16 @@ case SM_SLOC_EXPANSION_ENTRY: { SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]); - SourceMgr.createExpansionLoc(SpellingLoc, - ReadSourceLocation(*F, Record[2]), - ReadSourceLocation(*F, Record[3]), - Record[5], - Record[4], - ID, - BaseOffset + Record[0]); + unsigned SpellingLength = Record[2]; + SourceLocation ExpansionStart = ReadSourceLocation(*F, Record[3]); + bool EndIsToken = Record[4]; + bool EndIsRelative = Record[5]; + SourceLocation ExpansionEnd = + EndIsRelative ? ExpansionStart.getLocWithOffset(Record[6]) + : ReadSourceLocation(*F, Record[6]); + SourceMgr.createExpansionLoc(SpellingLoc, ExpansionStart, ExpansionEnd, + SpellingLength, EndIsToken, ID, + BaseOffset + Record[0]); break; } } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1689,19 +1689,47 @@ return Stream.EmitAbbrev(std::move(Abbrev)); } -/// Create an abbreviation for the SLocEntry that refers to a macro -/// expansion. -static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) { +/// We use a family of abbreviations for common cases of expansion SLocEntrys. +static std::shared_ptr SLocExpansionAbbrevCommon() { using namespace llvm; - auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_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::Fixed, 1)); // Is token range - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling start + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Spelling length + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Expansion start + Abbrev->Add(BitCodeAbbrevOp(1)); // ExpEnd is token + return Abbrev; +} + +/// Create an abbreviation for the SLocEntry that refers to a macro +/// argument expansion. +static unsigned CreateSLocArgExpansionAbbrev(llvm::BitstreamWriter &Stream) { + using namespace llvm; + auto Abbrev = SLocExpansionAbbrevCommon(); + Abbrev->Add(BitCodeAbbrevOp(0)); // ExpEnd is relative + Abbrev->Add(BitCodeAbbrevOp(0)); // ExpEnd + return Stream.EmitAbbrev(std::move(Abbrev)); +} + +/// Create an abbreviation for the SLocEntry that refers to a macro +/// expansion. +static unsigned CreateSLocObjectExpansionAbbrev(llvm::BitstreamWriter &Stream) { + using namespace llvm; + auto Abbrev = SLocExpansionAbbrevCommon(); + Abbrev->Add(BitCodeAbbrevOp(1)); // ExpEnd is relative + Abbrev->Add(BitCodeAbbrevOp(0)); // ExpEnd + return Stream.EmitAbbrev(std::move(Abbrev)); +} + +/// Create an abbreviation for the SLocEntry that refers to a function-like +/// macro expansion. +static unsigned +CreateSLocFunctionExpansionAbbrev(llvm::BitstreamWriter &Stream) { + using namespace llvm; + auto Abbrev = SLocExpansionAbbrevCommon(); + Abbrev->Add(BitCodeAbbrevOp(1)); // ExpEnd is relative + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End return Stream.EmitAbbrev(std::move(Abbrev)); } @@ -2018,7 +2046,10 @@ unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream, false); unsigned SLocBufferBlobCompressedAbbrv = CreateSLocBufferBlobAbbrev(Stream, true); - unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream); + unsigned SLocArgExpansionAbbrv = CreateSLocArgExpansionAbbrev(Stream); + unsigned SLocObjectExpansionAbbrv = CreateSLocObjectExpansionAbbrev(Stream); + unsigned SLocFunctionExpansionAbbrv = + CreateSLocFunctionExpansionAbbrev(Stream); // Write out the source location entry table. We skip the first // entry, which is always the same dummy entry. @@ -2123,19 +2154,47 @@ // The source location entry is a macro expansion. const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion(); AddSourceLocation(Expansion.getSpellingLoc(), Record); - AddSourceLocation(Expansion.getExpansionLocStart(), Record); - AddSourceLocation(Expansion.isMacroArgExpansion() - ? SourceLocation() - : Expansion.getExpansionLocEnd(), - Record); - Record.push_back(Expansion.isExpansionTokenRange()); - - // Compute the token length for this macro expansion. + // Compute the length for this macro expansion. SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset(); if (I + 1 != N) NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset(); Record.push_back(NextOffset - SLoc->getOffset() - 1); - Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record); + + // ExpStart, ExpEndIsToken, ExpEndIsRelative, ExpEnd + AddSourceLocation(Expansion.getExpansionLocStart(), Record); + Record.push_back(Expansion.isExpansionTokenRange()); + SourceLocation ExpEnd = Expansion.isMacroArgExpansion() + ? SourceLocation() + : Expansion.getExpansionLocEnd(); + SourceLocation::IntTy Delta; + bool EndIsRelative = + SourceMgr.isInSameSLocAddrSpace(Expansion.getExpansionLocStart(), + ExpEnd, &Delta) && + Delta >= 0; + Record.push_back(EndIsRelative); + if (EndIsRelative) + Record.push_back(Delta); + else + AddSourceLocation(ExpEnd, Record); + + // Common cases are covered by abbreviations. + unsigned Abbrev = [&]() -> unsigned { + if (!Expansion.isExpansionTokenRange()) // Token splits. + return 0; + if (Expansion.isMacroArgExpansion()) + return SLocArgExpansionAbbrv; + if (!EndIsRelative) // Expansion start/end in different FileIDs. + return 0; + if (Expansion.isFunctionMacroExpansion()) + return SLocFunctionExpansionAbbrv; + return SLocObjectExpansionAbbrv; + }(); + if (Abbrev) + Stream.EmitRecordWithAbbrev(Abbrev, Record); + else + Stream.EmitRecord(SM_SLOC_EXPANSION_ENTRY, + // To emit without abbrev, we must omit the code. + llvm::makeArrayRef(Record).drop_front(1)); } }