diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 3e1fb05ad537c..02a6fb5333538 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -3602,6 +3602,9 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { } NestedNameSpecifier *getQualifier() const { return Qualifier; } + /// Note: this can trigger extra deserialization when external AST sources are + /// used. Prefer `getCXXRecordDecl()` unless you really need the most recent + /// decl. CXXRecordDecl *getMostRecentCXXRecordDecl() const; bool isSugared() const; @@ -3610,7 +3613,10 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl()); + // FIXME: `getMostRecentCXXRecordDecl()` should be possible to use here, + // however when external AST sources are used it causes nondeterminism + // issues (see https://github.com/llvm/llvm-project/pull/137910). + Profile(ID, getPointeeType(), getQualifier(), getCXXRecordDecl()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, @@ -3620,6 +3626,9 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { static bool classof(const Type *T) { return T->getTypeClass() == MemberPointer; } + +private: + CXXRecordDecl *getCXXRecordDecl() const; }; /// Capture whether this is a normal array (e.g. int X[4]) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 111a642173418..a149eac7e4555 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5275,10 +5275,14 @@ void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, ID.AddPointer(Cls->getCanonicalDecl()); } +CXXRecordDecl *MemberPointerType::getCXXRecordDecl() const { + return dyn_cast(getCanonicalTypeInternal()) + ->getQualifier() + ->getAsRecordDecl(); +} + CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { - auto *RD = dyn_cast(getCanonicalTypeInternal()) - ->getQualifier() - ->getAsRecordDecl(); + auto *RD = getCXXRecordDecl(); if (!RD) return nullptr; return RD->getMostRecentNonInjectedDecl();