Skip to content

Commit 6c31104

Browse files
authored
[Modules] No transitive source location change (#86912)
This is part of "no transitive change" patch series, "no transitive source location change". I talked this with @Bigcheese in the tokyo's WG21 meeting. The idea comes from @jyknight posted on LLVM discourse. That for: ``` // A.cppm export module A; ... // B.cppm export module B; import A; ... //--- C.cppm export module C; import C; ``` Almost every time A.cppm changes, we need to recompile `B`. Due to we think the source location is significant to the semantics. But it may be good if we can avoid recompiling `C` if the change from `A` wouldn't change the BMI of B. # Motivation Example This patch only cares source locations. So let's focus on source location's example. We can see the full example from the attached test. ``` //--- A.cppm export module A; export template <class T> struct C { T func() { return T(43); } }; export int funcA() { return 43; } //--- A.v1.cppm export module A; export template <class T> struct C { T func() { return T(43); } }; export int funcA() { return 43; } //--- B.cppm export module B; import A; export int funcB() { return funcA(); } //--- C.cppm export module C; import A; export void testD() { C<int> c; c.func(); } ``` Here the only difference between `A.cppm` and `A.v1.cppm` is that `A.v1.cppm` has an additional blank line. Then the test shows that two BMI of `B.cppm`, one specified `-fmodule-file=A=A.pcm` and the other specified `-fmodule-file=A=A.v1.pcm`, should have the bit-wise same contents. However, it is a different story for C, since C instantiates templates from A, and the instantiation records the source information from module A, which is different from `A` and `A.v1`, so it is expected that the BMI `C.pcm` and `C.v1.pcm` can and should differ. # Internal perspective of status quo To fully understand the patch, we need to understand how we encodes source locations and how we serialize and deserialize them. For source locations, we encoded them as: ``` | | | _____ base offset of an imported module | | | |_____ base offset of another imported module | | | | | ___ 0 ``` As the diagram shows, we encode the local (unloaded) source location from 0 to higher bits. And we allocate the space for source locations from the loaded modules from high bits to 0. Then the source locations from the loaded modules will be mapped to our source location space according to the allocated offset. For example, for, ``` // a.cppm export module a; ... // b.cppm export module b; import a; ... ``` Assuming the offset of a source location (let's name the location as `S`) in a.cppm is 45 and we will record the value `45` into the BMI `a.pcm`. Then in b.cppm, when we import a, the source manager will allocate a space for module 'a' (according to the recorded number of source locations) as the base offset of module 'a' in the current source location spaces. Let's assume the allocated base offset as 90 in this example. Then when we want to get the location in the current source location space for `S`, we can get it simply by adding `45` to `90` to `135`. Finally we can get the source location for `S` in module B as `135`. And when we want to write module `b`, we would also write the source location of `S` as `135` directly in the BMI. And to clarify the location `S` comes from module `a`, we also need to record the base offset of module `a`, 90 in the BMI of `b`. Then the problem comes. Since the base offset of module 'a' is computed by the number source locations in module 'a'. In module 'b', the recorded base offset of module 'a' will change every time the number of source locations in module 'a' increase or decrease. In other words, the contents of BMI of B will change every time the number of locations in module 'a' changes. This is pretty sensitive. Almost every change will change the number of locations. So this is the problem this patch want to solve. Let's continue with the existing design to understand what's going on. Another interesting case is: ``` // c.cppm export module c; import whatever; import a; import b; ... ``` In `c.cppm`, when we import `a`, we still need to allocate a base location offset for it, let's say the value becomes to `200` somehow. Then when we reach the location `S` recorded in module `b`, we need to translate it into the current source location space. The solution is quite simple, we can get it by `135 + (200 - 90) = 245`. In another word, the offset of a source location in current module can be computed as `Recorded Offset + Base Offset of the its module file - Recorded Base Offset`. Then we're almost done about how we handle the offset of source locations in serializers. # The high level design of current patch From the abstract level, what we want to do is to remove the hardcoded base offset of imported modules and remain the ability to calculate the source location in a new module unit. To achieve this, we need to be able to find the module file owning a source location from the encoding of the source location. So in this patch, for each source location, we will store the local offset of the location and the module file index. For the above example, in `b.pcm`, the source location of `S` will be recorded as `135` directly. And in the new design, the source location of `S` will be recorded as `<1, 45>`. Here `1` stands for the module file index of `a` in module `b`. And `45` means the offset of `S` to the base offset of module `a`. So the trade-off here is that, to make the BMI more independent, we need to record more abstract information. And I feel it is worthy. The recompilation problem of modules is really annoying and there are still people complaining this. But if we can make this (including stopping other changes transitively), I think this may be a killer feature for modules. And from @Bigcheese , this should be helpful for clang explicit modules too. And the benchmarking side, I tested this patch against https://github.com/alibaba/async_simple/tree/CXX20Modules. No significant change on compilation time. The size of .pcm files becomes to 204M from 200M. I think the trade-off is pretty fair. # Some low level details I didn't use another slot to record the module file index. I tried to use the higher 32 bits of the existing source location encodings to store that information. This design may be safe. Since we use `unsigned` to store source locations but we use uint64_t in serialization. And generally `unsigned` is 32 bit width in most platforms. So it might not be a safe problem. Since all the bits we used to store the module file index is not used before. So the new encodings may be: ``` |-----------------------|-----------------------| | A | B | C | * A: 32 bit. The index of the module file in the module manager + 1. The +1 here is necessary since we wish 0 stands for the current module file. * B: 31 bit. The offset of the source location to the module file containing it. * C: The macro bit. We rotate it to the lowest bit so that we can save some space in case the index of the module file is 0. ``` (The B and C is the existing raw encoding for source locations) Another reason to reuse the same slot of the source location is to reduce the impact of the patch. Since there are a lot of places assuming we can store and get a source location from a slot. And if I tried to add another slot, a lot of codes breaks. I don't feel it is worhty. Another impact of this decision is that, the existing small optimizations for encoding source location may be invalided. The key of the optimization is that we can turn large values into small values then we can use VBR6 format to reduce the size. But if we decided to put the module file index into the higher bits, then maybe it simply doesn't work. An example may be the `SourceLocationSequence` optimization. This will only affect the size of on-disk .pcm files. I don't expect this impact the speed and memory use of compilations. And seeing my small experiments above, I feel this trade off is worthy. # Correctness The mental model for handling source location offsets is not so complex and I believe we can solve it by adding module file index to each stored source location. For the practical side, since the source location is pretty sensitive, and the patch can pass all the in-tree tests and a small scale projects, I feel it should be correct. # Future Plans I'll continue to work on no transitive decl change and no transitive identifier change (if matters) to achieve the goal to stop the propagation of unnecessary changes. But all of this depends on this patch. Since, clearly, the source locations are the most sensitive thing. --- The release nots and documentation will be added seperately.
1 parent 853344d commit 6c31104

File tree

15 files changed

+269
-162
lines changed

15 files changed

+269
-162
lines changed

clang/include/clang/Basic/SourceLocation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class SourceLocation {
9090
friend class ASTWriter;
9191
friend class SourceManager;
9292
friend struct llvm::FoldingSetTrait<SourceLocation, void>;
93+
friend class SourceLocationEncoding;
9394

9495
public:
9596
using UIntTy = uint32_t;

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "clang/Basic/IdentifierTable.h"
2424
#include "clang/Basic/OperatorKinds.h"
2525
#include "clang/Basic/SourceLocation.h"
26+
#include "clang/Serialization/SourceLocationEncoding.h"
2627
#include "llvm/ADT/DenseMapInfo.h"
2728
#include "llvm/Bitstream/BitCodes.h"
2829
#include <cassert>
@@ -167,45 +168,38 @@ const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
167168

168169
/// Source range/offset of a preprocessed entity.
169170
struct PPEntityOffset {
171+
using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
172+
170173
/// Raw source location of beginning of range.
171-
SourceLocation::UIntTy Begin;
174+
RawLocEncoding Begin;
172175

173176
/// Raw source location of end of range.
174-
SourceLocation::UIntTy End;
177+
RawLocEncoding End;
175178

176179
/// Offset in the AST file relative to ModuleFile::MacroOffsetsBase.
177180
uint32_t BitOffset;
178181

179-
PPEntityOffset(SourceRange R, uint32_t BitOffset)
180-
: Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()),
181-
BitOffset(BitOffset) {}
182-
183-
SourceLocation getBegin() const {
184-
return SourceLocation::getFromRawEncoding(Begin);
185-
}
182+
PPEntityOffset(RawLocEncoding Begin, RawLocEncoding End, uint32_t BitOffset)
183+
: Begin(Begin), End(End), BitOffset(BitOffset) {}
186184

187-
SourceLocation getEnd() const {
188-
return SourceLocation::getFromRawEncoding(End);
189-
}
185+
RawLocEncoding getBegin() const { return Begin; }
186+
RawLocEncoding getEnd() const { return End; }
190187
};
191188

192189
/// Source range of a skipped preprocessor region
193190
struct PPSkippedRange {
191+
using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
192+
194193
/// Raw source location of beginning of range.
195-
SourceLocation::UIntTy Begin;
194+
RawLocEncoding Begin;
196195
/// Raw source location of end of range.
197-
SourceLocation::UIntTy End;
196+
RawLocEncoding End;
198197

199-
PPSkippedRange(SourceRange R)
200-
: Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()) {
201-
}
198+
PPSkippedRange(RawLocEncoding Begin, RawLocEncoding End)
199+
: Begin(Begin), End(End) {}
202200

203-
SourceLocation getBegin() const {
204-
return SourceLocation::getFromRawEncoding(Begin);
205-
}
206-
SourceLocation getEnd() const {
207-
return SourceLocation::getFromRawEncoding(End);
208-
}
201+
RawLocEncoding getBegin() const { return Begin; }
202+
RawLocEncoding getEnd() const { return End; }
209203
};
210204

211205
/// Offset in the AST file. Use splitted 64-bit integer into low/high
@@ -231,26 +225,26 @@ struct UnderalignedInt64 {
231225

232226
/// Source location and bit offset of a declaration.
233227
struct DeclOffset {
228+
using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
229+
234230
/// Raw source location.
235-
SourceLocation::UIntTy Loc = 0;
231+
RawLocEncoding RawLoc = 0;
236232

237233
/// Offset relative to the start of the DECLTYPES_BLOCK block. Keep
238234
/// structure alignment 32-bit and avoid padding gap because undefined
239235
/// value in the padding affects AST hash.
240236
UnderalignedInt64 BitOffset;
241237

242238
DeclOffset() = default;
243-
DeclOffset(SourceLocation Loc, uint64_t BitOffset,
244-
uint64_t DeclTypesBlockStartOffset) {
245-
setLocation(Loc);
239+
DeclOffset(RawLocEncoding RawLoc, uint64_t BitOffset,
240+
uint64_t DeclTypesBlockStartOffset)
241+
: RawLoc(RawLoc) {
246242
setBitOffset(BitOffset, DeclTypesBlockStartOffset);
247243
}
248244

249-
void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); }
245+
void setRawLoc(RawLocEncoding Loc) { RawLoc = Loc; }
250246

251-
SourceLocation getLocation() const {
252-
return SourceLocation::getFromRawEncoding(Loc);
253-
}
247+
RawLocEncoding getRawLoc() const { return RawLoc; }
254248

255249
void setBitOffset(uint64_t Offset, const uint64_t DeclTypesBlockStartOffset) {
256250
BitOffset.setBitOffset(Offset - DeclTypesBlockStartOffset);

clang/include/clang/Serialization/ASTReader.h

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,7 @@ class ASTReader
17711771

17721772
/// Retrieve the module manager.
17731773
ModuleManager &getModuleManager() { return ModuleMgr; }
1774+
const ModuleManager &getModuleManager() const { return ModuleMgr; }
17741775

17751776
/// Retrieve the preprocessor.
17761777
Preprocessor &getPreprocessor() const { return PP; }
@@ -2177,8 +2178,8 @@ class ASTReader
21772178

21782179
/// Retrieve the global submodule ID given a module and its local ID
21792180
/// number.
2180-
serialization::SubmoduleID
2181-
getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID);
2181+
serialization::SubmoduleID getGlobalSubmoduleID(ModuleFile &M,
2182+
unsigned LocalID) const;
21822183

21832184
/// Retrieve the submodule that corresponds to a global submodule ID.
21842185
///
@@ -2191,7 +2192,7 @@ class ASTReader
21912192

21922193
/// Retrieve the module file with a given local ID within the specified
21932194
/// ModuleFile.
2194-
ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID);
2195+
ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID) const;
21952196

21962197
/// Get an ID for the given module file.
21972198
unsigned getModuleFileID(ModuleFile *M);
@@ -2227,33 +2228,46 @@ class ASTReader
22272228
return Sema::AlignPackInfo::getFromRawEncoding(Raw);
22282229
}
22292230

2231+
using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
2232+
22302233
/// Read a source location from raw form and return it in its
22312234
/// originating module file's source location space.
2232-
SourceLocation ReadUntranslatedSourceLocation(SourceLocation::UIntTy Raw,
2233-
LocSeq *Seq = nullptr) const {
2235+
std::pair<SourceLocation, unsigned>
2236+
ReadUntranslatedSourceLocation(RawLocEncoding Raw,
2237+
LocSeq *Seq = nullptr) const {
22342238
return SourceLocationEncoding::decode(Raw, Seq);
22352239
}
22362240

22372241
/// Read a source location from raw form.
2238-
SourceLocation ReadSourceLocation(ModuleFile &ModuleFile,
2239-
SourceLocation::UIntTy Raw,
2242+
SourceLocation ReadSourceLocation(ModuleFile &MF, RawLocEncoding Raw,
22402243
LocSeq *Seq = nullptr) const {
2241-
SourceLocation Loc = ReadUntranslatedSourceLocation(Raw, Seq);
2242-
return TranslateSourceLocation(ModuleFile, Loc);
2244+
if (!MF.ModuleOffsetMap.empty())
2245+
ReadModuleOffsetMap(MF);
2246+
2247+
auto [Loc, ModuleFileIndex] = ReadUntranslatedSourceLocation(Raw, Seq);
2248+
ModuleFile *OwningModuleFile =
2249+
ModuleFileIndex == 0 ? &MF : MF.DependentModules[ModuleFileIndex - 1];
2250+
2251+
assert(!SourceMgr.isLoadedSourceLocation(Loc) &&
2252+
"Run out source location space");
2253+
2254+
return TranslateSourceLocation(*OwningModuleFile, Loc);
22432255
}
22442256

22452257
/// Translate a source location from another module file's source
22462258
/// location space into ours.
22472259
SourceLocation TranslateSourceLocation(ModuleFile &ModuleFile,
22482260
SourceLocation Loc) const {
2249-
if (!ModuleFile.ModuleOffsetMap.empty())
2250-
ReadModuleOffsetMap(ModuleFile);
2251-
assert(ModuleFile.SLocRemap.find(Loc.getOffset()) !=
2252-
ModuleFile.SLocRemap.end() &&
2253-
"Cannot find offset to remap.");
2254-
SourceLocation::IntTy Remap =
2255-
ModuleFile.SLocRemap.find(Loc.getOffset())->second;
2256-
return Loc.getLocWithOffset(Remap);
2261+
if (Loc.isInvalid())
2262+
return Loc;
2263+
2264+
// FIXME: TranslateSourceLocation is not re-enterable. It is problematic
2265+
// to call TranslateSourceLocation on a translated source location.
2266+
// We either need a method to know whether or not a source location is
2267+
// translated or refactor the code to make it clear that
2268+
// TranslateSourceLocation won't be called with translated source location.
2269+
2270+
return Loc.getLocWithOffset(ModuleFile.SLocEntryBaseOffset - 2);
22572271
}
22582272

22592273
/// Read a source location.

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,10 @@ class ASTWriter : public ASTDeserializationListener,
666666
void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record,
667667
LocSeq *Seq = nullptr);
668668

669+
/// Return the raw encodings for source locations.
670+
SourceLocationEncoding::RawLocEncoding
671+
getRawSourceLocationEncoding(SourceLocation Loc, LocSeq *Seq = nullptr);
672+
669673
/// Emit a source range.
670674
void AddSourceRange(SourceRange Range, RecordDataImpl &Record,
671675
LocSeq *Seq = nullptr);

clang/include/clang/Serialization/ModuleFile.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,6 @@ class ModuleFile {
295295
/// AST file.
296296
const uint32_t *SLocEntryOffsets = nullptr;
297297

298-
/// Remapping table for source locations in this module.
299-
ContinuousRangeMap<SourceLocation::UIntTy, SourceLocation::IntTy, 2>
300-
SLocRemap;
301-
302298
// === Identifiers ===
303299

304300
/// The number of identifiers in this AST file.
@@ -512,9 +508,17 @@ class ModuleFile {
512508
/// List of modules which depend on this module
513509
llvm::SetVector<ModuleFile *> ImportedBy;
514510

515-
/// List of modules which this module depends on
511+
/// List of modules which this module directly imported
516512
llvm::SetVector<ModuleFile *> Imports;
517513

514+
/// List of modules which this modules dependent on. Different
515+
/// from `Imports`, this includes indirectly imported modules too.
516+
/// The order of DependentModules is significant. It should keep
517+
/// the same order with that module file manager when we write
518+
/// the current module file. The value of the member will be initialized
519+
/// in `ASTReader::ReadModuleOffsetMap`.
520+
llvm::SmallVector<ModuleFile *, 16> DependentModules;
521+
518522
/// Determine whether this module was directly imported at
519523
/// any point during translation.
520524
bool isDirectlyImported() const { return DirectlyImported; }

clang/include/clang/Serialization/SourceLocationEncoding.h

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,33 @@
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// Source locations are stored pervasively in the AST, making up a third of
10-
// the size of typical serialized files. Storing them efficiently is important.
9+
// We wish to encode the SourceLocation from other module file not dependent
10+
// on the other module file. So that the source location changes from other
11+
// module file may not affect the contents of the current module file. Then the
12+
// users don't need to recompile the whole project due to a new line in a module
13+
// unit in the root of the dependency graph.
1114
//
12-
// We use integers optimized by VBR-encoding, because:
13-
// - when abbreviations cannot be used, VBR6 encoding is our only choice
14-
// - in the worst case a SourceLocation can be ~any 32-bit number, but in
15-
// practice they are highly predictable
15+
// To achieve this, we need to encode the index of the module file into the
16+
// encoding of the source location. The encoding of the source location may be:
1617
//
17-
// We encode the integer so that likely values encode as small numbers that
18-
// turn into few VBR chunks:
19-
// - the invalid sentinel location is a very common value: it encodes as 0
20-
// - the "macro or not" bit is stored at the bottom of the integer
21-
// (rather than at the top, as in memory), so macro locations can have
22-
// small representations.
23-
// - related locations (e.g. of a left and right paren pair) are usually
24-
// similar, so when encoding a sequence of locations we store only
25-
// differences between successive elements.
18+
// |-----------------------|-----------------------|
19+
// | A | B | C |
20+
//
21+
// * A: 32 bit. The index of the module file in the module manager + 1. The +1
22+
// here is necessary since we wish 0 stands for the current module file.
23+
// * B: 31 bit. The offset of the source location to the module file containing
24+
// it.
25+
// * C: The macro bit. We rotate it to the lowest bit so that we can save some
26+
// space in case the index of the module file is 0.
27+
//
28+
// Specially, if the index of the module file is 0, we allow to encode a
29+
// sequence of locations we store only differences between successive elements.
2630
//
2731
//===----------------------------------------------------------------------===//
2832

29-
#include <climits>
3033
#include "clang/Basic/SourceLocation.h"
34+
#include "llvm/Support/MathExtras.h"
35+
#include <climits>
3136

3237
#ifndef LLVM_CLANG_SERIALIZATION_SOURCELOCATIONENCODING_H
3338
#define LLVM_CLANG_SERIALIZATION_SOURCELOCATIONENCODING_H
@@ -52,9 +57,13 @@ class SourceLocationEncoding {
5257
friend SourceLocationSequence;
5358

5459
public:
55-
static uint64_t encode(SourceLocation Loc,
56-
SourceLocationSequence * = nullptr);
57-
static SourceLocation decode(uint64_t, SourceLocationSequence * = nullptr);
60+
using RawLocEncoding = uint64_t;
61+
62+
static RawLocEncoding encode(SourceLocation Loc, UIntTy BaseOffset,
63+
unsigned BaseModuleFileIndex,
64+
SourceLocationSequence * = nullptr);
65+
static std::pair<SourceLocation, unsigned>
66+
decode(RawLocEncoding, SourceLocationSequence * = nullptr);
5867
};
5968

6069
/// Serialized encoding of a sequence of SourceLocations.
@@ -149,14 +158,44 @@ class SourceLocationSequence::State {
149158
operator SourceLocationSequence *() { return &Seq; }
150159
};
151160

152-
inline uint64_t SourceLocationEncoding::encode(SourceLocation Loc,
153-
SourceLocationSequence *Seq) {
154-
return Seq ? Seq->encode(Loc) : encodeRaw(Loc.getRawEncoding());
161+
inline SourceLocationEncoding::RawLocEncoding
162+
SourceLocationEncoding::encode(SourceLocation Loc, UIntTy BaseOffset,
163+
unsigned BaseModuleFileIndex,
164+
SourceLocationSequence *Seq) {
165+
// If the source location is a local source location, we can try to optimize
166+
// the similar sequences to only record the differences.
167+
if (!BaseOffset)
168+
return Seq ? Seq->encode(Loc) : encodeRaw(Loc.getRawEncoding());
169+
170+
if (Loc.isInvalid())
171+
return 0;
172+
173+
// Otherwise, the higher bits are used to store the module file index,
174+
// so it is meaningless to optimize the source locations into small
175+
// integers. Let's try to always use the raw encodings.
176+
assert(Loc.getOffset() >= BaseOffset);
177+
Loc = Loc.getLocWithOffset(-BaseOffset);
178+
RawLocEncoding Encoded = encodeRaw(Loc.getRawEncoding());
179+
180+
// 16 bits should be sufficient to store the module file index.
181+
assert(BaseModuleFileIndex < (1 << 16));
182+
Encoded |= (RawLocEncoding)BaseModuleFileIndex << 32;
183+
return Encoded;
155184
}
156-
inline SourceLocation
157-
SourceLocationEncoding::decode(uint64_t Encoded, SourceLocationSequence *Seq) {
158-
return Seq ? Seq->decode(Encoded)
159-
: SourceLocation::getFromRawEncoding(decodeRaw(Encoded));
185+
inline std::pair<SourceLocation, unsigned>
186+
SourceLocationEncoding::decode(RawLocEncoding Encoded,
187+
SourceLocationSequence *Seq) {
188+
unsigned ModuleFileIndex = Encoded >> 32;
189+
190+
if (!ModuleFileIndex)
191+
return {Seq ? Seq->decode(Encoded)
192+
: SourceLocation::getFromRawEncoding(decodeRaw(Encoded)),
193+
ModuleFileIndex};
194+
195+
Encoded &= llvm::maskTrailingOnes<RawLocEncoding>(32);
196+
SourceLocation Loc = SourceLocation::getFromRawEncoding(decodeRaw(Encoded));
197+
198+
return {Loc, ModuleFileIndex};
160199
}
161200

162201
} // namespace clang

clang/lib/Frontend/ASTUnit.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2374,8 +2374,6 @@ bool ASTUnit::serialize(raw_ostream &OS) {
23742374
return serializeUnit(Writer, Buffer, getSema(), OS);
23752375
}
23762376

2377-
using SLocRemap = ContinuousRangeMap<unsigned, int, 2>;
2378-
23792377
void ASTUnit::TranslateStoredDiagnostics(
23802378
FileManager &FileMgr,
23812379
SourceManager &SrcMgr,

0 commit comments

Comments
 (0)