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