@@ -29,6 +29,16 @@ struct IndexRecordHasher {
29
29
llvm::HashBuilder<llvm::TruncatedBLAKE3<8 >, llvm::endianness::little>
30
30
HashBuilder;
31
31
32
+ // / Maps declarations that have already been hashed in this
33
+ // / `IndexRecordHasher` to a unique ID that identifies this declaration.
34
+ // /
35
+ // / The ID assigned to a declaration is consistent across multiple runs of the
36
+ // / `IndexRecordHasher` on the same AST structure, even across multiple
37
+ // / process runs.
38
+ // /
39
+ // / See `hashDecl` for its use.
40
+ llvm::DenseMap<const Decl *, size_t > HashedDecls;
41
+
32
42
explicit IndexRecordHasher (ASTContext &context) : Ctx(context) {}
33
43
34
44
void hashDecl (const Decl *D);
@@ -185,6 +195,19 @@ void IndexRecordHasher::hashMacro(const IdentifierInfo *name,
185
195
void IndexRecordHasher::hashDecl (const Decl *D) {
186
196
assert (D->isCanonicalDecl ());
187
197
198
+ auto emplaceResult = HashedDecls.try_emplace (D, HashedDecls.size ());
199
+ bool inserted = emplaceResult.second ;
200
+ if (!inserted) {
201
+ // If we have already serialized this declaration, just add the
202
+ // declaration's hash to the hash builder. This is significantly
203
+ // cheaper than visiting the declaration again.
204
+ HashBuilder.add (emplaceResult.first ->second );
205
+ return ;
206
+ }
207
+
208
+ // If we haven't serialized the declaration yet,`try_emplace` will insert the
209
+ // new unique ID into `HashedDecls`. We just need to hash the declaration
210
+ // once.
188
211
if (auto *NS = dyn_cast<NamespaceDecl>(D)) {
189
212
if (NS->isAnonymousNamespace ()) {
190
213
HashBuilder.add (" @aN" );
0 commit comments