Skip to content

Commit d89d2d0

Browse files
emaxx-googleIanWood1
authored andcommitted
[clang] Fix nondeterminism in MemberPointerType (llvm#137910)
This commit fixes the nondeterminism issue in C++ header module enabled builds which were observed after llvm#132401. The issue was related to the fact that the hash set operation in MemberPointerType::Profile() was triggering getMostRecentDecl(). As the latter may trigger the loading of new entities from the external AST source, this was presumably causing reentrant modification of data structure or some other issue that affects compiler's output in a nondeterministic way (likely depending on specific values hashes/pointers have). The change should otherwise be a no-op, because whether we take a "most recent" or "any" Decl shouldn't matter since `getCanonicalDecl()` is called on it anyway inside `MemberPointerType::Profile()`. We haven't been able to come up with a deterministic regression test for this fix.
1 parent 3752b7d commit d89d2d0

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

clang/include/clang/AST/Type.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3602,6 +3602,9 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
36023602
}
36033603

36043604
NestedNameSpecifier *getQualifier() const { return Qualifier; }
3605+
/// Note: this can trigger extra deserialization when external AST sources are
3606+
/// used. Prefer `getCXXRecordDecl()` unless you really need the most recent
3607+
/// decl.
36053608
CXXRecordDecl *getMostRecentCXXRecordDecl() const;
36063609

36073610
bool isSugared() const;
@@ -3610,7 +3613,10 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
36103613
}
36113614

36123615
void Profile(llvm::FoldingSetNodeID &ID) {
3613-
Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
3616+
// FIXME: `getMostRecentCXXRecordDecl()` should be possible to use here,
3617+
// however when external AST sources are used it causes nondeterminism
3618+
// issues (see https://github.com/llvm/llvm-project/pull/137910).
3619+
Profile(ID, getPointeeType(), getQualifier(), getCXXRecordDecl());
36143620
}
36153621

36163622
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
@@ -3620,6 +3626,9 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
36203626
static bool classof(const Type *T) {
36213627
return T->getTypeClass() == MemberPointer;
36223628
}
3629+
3630+
private:
3631+
CXXRecordDecl *getCXXRecordDecl() const;
36233632
};
36243633

36253634
/// Capture whether this is a normal array (e.g. int X[4])

clang/lib/AST/Type.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5305,10 +5305,14 @@ void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
53055305
ID.AddPointer(Cls->getCanonicalDecl());
53065306
}
53075307

5308+
CXXRecordDecl *MemberPointerType::getCXXRecordDecl() const {
5309+
return dyn_cast<MemberPointerType>(getCanonicalTypeInternal())
5310+
->getQualifier()
5311+
->getAsRecordDecl();
5312+
}
5313+
53085314
CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
5309-
auto *RD = dyn_cast<MemberPointerType>(getCanonicalTypeInternal())
5310-
->getQualifier()
5311-
->getAsRecordDecl();
5315+
auto *RD = getCXXRecordDecl();
53125316
if (!RD)
53135317
return nullptr;
53145318
return RD->getMostRecentNonInjectedDecl();

0 commit comments

Comments
 (0)