[clang] [clang] Fix the crash when dumping deserialized decls (PR #133395)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 28 02:46:07 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Haojian Wu (hokein)
<details>
<summary>Changes</summary>
This fixes crashes with `-dump-deserialized-decls`.
The `DeserializedDeclsDumper` implementation has two issues:
1. The `DelegatingDeserializationListener` does not fully implement all interfaces. As a result, the `Previous` listener object misses some critical state updates, leading to inconsistencies and eventual crashes;
3. Print declaration names in the middle of deserialization is not safe, because the decl may still be incomplete; we should do it after the deserialization is finished;
No unittest is included -- crash was discovered by @<!-- -->VitaNuo in an internal isolated test which is still large, depending on the stl/absl modules. The issue no longer occurs with this change.
---
Full diff: https://github.com/llvm/llvm-project/pull/133395.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+1)
- (modified) clang/include/clang/Serialization/ASTDeserializationListener.h (+4)
- (modified) clang/lib/Frontend/FrontendAction.cpp (+38-6)
- (modified) clang/lib/Serialization/ASTReader.cpp (+2)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 04ec2cfef679c..9ae29d7e58626 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -316,6 +316,7 @@ Bug Fixes in This Version
- Fixed a modules crash where exception specifications were not propagated properly (#GH121245, relanded in #GH129982)
- Fixed a problematic case with recursive deserialization within ``FinishedDeserializing()`` where
``PassInterestingDeclsToConsumer()`` was called before the declarations were safe to be passed. (#GH129982)
+- Fixed a module crash with `-dump-deserialized-decls`
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Serialization/ASTDeserializationListener.h b/clang/include/clang/Serialization/ASTDeserializationListener.h
index ea96faa07c191..ccbaae93f9048 100644
--- a/clang/include/clang/Serialization/ASTDeserializationListener.h
+++ b/clang/include/clang/Serialization/ASTDeserializationListener.h
@@ -27,6 +27,8 @@ class MacroInfo;
class Module;
class SourceLocation;
+// IMPORTANT: when you add a new interface to this class, please update the
+// DelegatingDeserializationListener in FrontendAction.cpp
class ASTDeserializationListener {
public:
virtual ~ASTDeserializationListener();
@@ -57,6 +59,8 @@ class ASTDeserializationListener {
/// A module import was read from the AST file.
virtual void ModuleImportRead(serialization::SubmoduleID ID,
SourceLocation ImportLoc) {}
+ /// The deserialization of the AST file was finished.
+ virtual void FinishedDeserializing() {}
};
}
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 9f789f093f55d..416ee50593e74 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -76,6 +76,10 @@ class DelegatingDeserializationListener : public ASTDeserializationListener {
if (Previous)
Previous->IdentifierRead(ID, II);
}
+ void MacroRead(serialization::MacroID ID, MacroInfo *MI) override {
+ if (Previous)
+ Previous->MacroRead(ID, MI);
+ }
void TypeRead(serialization::TypeIdx Idx, QualType T) override {
if (Previous)
Previous->TypeRead(Idx, T);
@@ -93,6 +97,19 @@ class DelegatingDeserializationListener : public ASTDeserializationListener {
if (Previous)
Previous->MacroDefinitionRead(PPID, MD);
}
+ void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override {
+ if (Previous)
+ Previous->ModuleRead(ID, Mod);
+ }
+ void ModuleImportRead(serialization::SubmoduleID ID,
+ SourceLocation ImportLoc) override {
+ if (Previous)
+ Previous->ModuleImportRead(ID, ImportLoc);
+ }
+ void FinishedDeserializing() override {
+ if (Previous)
+ Previous->FinishedDeserializing();
+ }
};
/// Dumps deserialized declarations.
@@ -103,15 +120,30 @@ class DeserializedDeclsDumper : public DelegatingDeserializationListener {
: DelegatingDeserializationListener(Previous, DeletePrevious) {}
void DeclRead(GlobalDeclID ID, const Decl *D) override {
- llvm::outs() << "PCH DECL: " << D->getDeclKindName();
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- llvm::outs() << " - ";
- ND->printQualifiedName(llvm::outs());
+ PendingDecls.push_back(D);
+ DelegatingDeserializationListener::DeclRead(ID, D);
+ }
+ void FinishedDeserializing() override {
+ auto Decls = std::move(PendingDecls);
+ for (const auto *D : Decls) {
+ llvm::outs() << "PCH DECL: " << D->getDeclKindName();
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ llvm::outs() << " - ";
+ ND->printQualifiedName(llvm::outs());
+ }
+ llvm::outs() << "\n";
}
- llvm::outs() << "\n";
- DelegatingDeserializationListener::DeclRead(ID, D);
+ if (!PendingDecls.empty()) {
+ llvm::errs() << "Deserialized more decls while printing, total of "
+ << PendingDecls.size() << "\n";
+ PendingDecls.clear();
+ }
+ DelegatingDeserializationListener::FinishedDeserializing();
}
+
+private:
+ std::vector<const Decl *> PendingDecls;
};
/// Checks deserialized declarations and emits error if a name
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0cd2cedb48dd9..9e3712226491a 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10877,6 +10877,8 @@ void ASTReader::FinishedDeserializing() {
// decls to the consumer.
if (Consumer)
PassInterestingDeclsToConsumer();
+ if (DeserializationListener)
+ DeserializationListener->FinishedDeserializing();
}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/133395
More information about the cfe-commits
mailing list