Skip to content

Commit c28fd2b

Browse files
committed
[C++20][Modules] Fix non-determinism in serialized AST
Summary: llvm#109167 serialized FunctionToLambdasMap in the order of pointers in DenseMap. It gives different order with different memeory leayout. Fix this issue by using LocalDeclID instead of pointers. Test Plan: check-clang
1 parent 00ab44e commit c28fd2b

File tree

4 files changed

+28
-6
lines changed

4 files changed

+28
-6
lines changed

clang/include/clang/AST/DeclID.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ class LocalDeclID : public DeclIDBase {
189189
// Every Decl ID is a local decl ID to the module being writing in ASTWriter.
190190
friend class ASTWriter;
191191
friend class GlobalDeclID;
192+
friend struct llvm::DenseMapInfo<clang::LocalDeclID>;
192193

193194
public:
194195
LocalDeclID() : Base() {}
@@ -267,6 +268,27 @@ template <> struct DenseMapInfo<clang::GlobalDeclID> {
267268
}
268269
};
269270

271+
template <> struct DenseMapInfo<clang::LocalDeclID> {
272+
using LocalDeclID = clang::LocalDeclID;
273+
using DeclID = LocalDeclID::DeclID;
274+
275+
static LocalDeclID getEmptyKey() {
276+
return LocalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
277+
}
278+
279+
static LocalDeclID getTombstoneKey() {
280+
return LocalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
281+
}
282+
283+
static unsigned getHashValue(const LocalDeclID &Key) {
284+
return DenseMapInfo<DeclID>::getHashValue(Key.getRawValue());
285+
}
286+
287+
static bool isEqual(const LocalDeclID &L, const LocalDeclID &R) {
288+
return L == R;
289+
}
290+
};
291+
270292
} // namespace llvm
271293

272294
#endif

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,13 @@ class ASTWriter : public ASTDeserializationListener,
233233
/// instead of comparing the result of `getDeclID()` or `GetDeclRef()`.
234234
llvm::SmallPtrSet<const Decl *, 32> PredefinedDecls;
235235

236-
/// Mapping from FunctionDecl to the list of lambda IDs inside the function.
236+
/// Mapping from FunctionDecl ID to the list of lambda IDs inside the
237+
/// function.
237238
///
238239
/// These lambdas have to be loaded right after the function they belong to.
239240
/// In order to have canonical declaration for lambda class from the same
240241
/// module as enclosing function during deserialization.
241-
llvm::DenseMap<const Decl *, SmallVector<LocalDeclID, 4>>
242-
FunctionToLambdasMap;
242+
llvm::DenseMap<LocalDeclID, SmallVector<LocalDeclID, 4>> FunctionToLambdasMap;
243243

244244
/// Offset of each declaration in the bitstream, indexed by
245245
/// the declaration's ID.

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5713,8 +5713,7 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
57135713
// efficent becuase it allows lazy deserialization.
57145714
RecordData FunctionToLambdasMapRecord;
57155715
for (const auto &Pair : FunctionToLambdasMap) {
5716-
FunctionToLambdasMapRecord.push_back(
5717-
GetDeclRef(Pair.first).getRawValue());
5716+
FunctionToLambdasMapRecord.push_back(Pair.first.getRawValue());
57185717
FunctionToLambdasMapRecord.push_back(Pair.second.size());
57195718
for (const auto &Lambda : Pair.second)
57205719
FunctionToLambdasMapRecord.push_back(Lambda.getRawValue());

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1524,7 +1524,8 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
15241524
// For lambdas inside canonical FunctionDecl remember the mapping.
15251525
if (auto FD = llvm::dyn_cast_or_null<FunctionDecl>(D->getDeclContext());
15261526
FD && FD->isCanonicalDecl()) {
1527-
Writer.FunctionToLambdasMap[FD].push_back(Writer.GetDeclRef(D));
1527+
Writer.FunctionToLambdasMap[Writer.GetDeclRef(FD)].push_back(
1528+
Writer.GetDeclRef(D));
15281529
}
15291530
} else {
15301531
Record.push_back(CXXRecNotTemplate);

0 commit comments

Comments
 (0)