[Lldb-commits] [lldb] 770cd24 - [lldb][ClangExpressionParser] Don't leak memory when multiplexing ExternalASTSources (#104799)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Aug 20 10:40:57 PDT 2024
Author: Michael Buch
Date: 2024-08-20T18:40:54+01:00
New Revision: 770cd24140038646539602406fff54497793dae8
URL: https://github.com/llvm/llvm-project/commit/770cd24140038646539602406fff54497793dae8
DIFF: https://github.com/llvm/llvm-project/commit/770cd24140038646539602406fff54497793dae8.diff
LOG: [lldb][ClangExpressionParser] Don't leak memory when multiplexing ExternalASTSources (#104799)
When we use `SemaSourceWithPriorities` as the `ASTContext`s
ExternalASTSource, we allocate a `ClangASTSourceProxy` (via
`CreateProxy`) and two `ExternalASTSourceWrapper`. Then we push these
sources into a vector in `SemaSourceWithPriorities`. The allocated
`SemaSourceWithPriorities` itself will get properly deallocated because
the `ASTContext` wraps it in an `IntrusiveRefCntPtr`. But the three
sources we allocated earlier will never get released.
This patch fixes this by mimicking what `MultiplexExternalSemaSource`
does (which is what `SemaSourceWithPriorities` is based on anyway).
I.e., when `SemaSourceWithPriorities` gets constructed, it increments
the use count of its sources. And on destruction it decrements them.
Similarly, to make sure we dealloacted the `ClangASTProxy` properly, the
`ExternalASTSourceWrapper` now assumes shared ownership of the
underlying source.
Added:
Modified:
lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
index a95fce1c5aa966..5d67a51b269051 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
@@ -18,7 +18,10 @@ lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() = default;
void lldb_private::ASTConsumerForwarder::PrintStats() { m_c->PrintStats(); }
-lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() = default;
+lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() {
+ for (auto *Source : Sources)
+ Source->Release();
+}
void lldb_private::SemaSourceWithPriorities::PrintStats() {
for (size_t i = 0; i < Sources.size(); ++i)
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
index 79ed74b79f04fd..44e52e8dd65113 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
@@ -14,6 +14,7 @@
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include <optional>
namespace clang {
@@ -24,13 +25,15 @@ class Module;
namespace lldb_private {
-/// Wraps an ExternalASTSource into an ExternalSemaSource. Doesn't take
-/// ownership of the provided source.
+/// Wraps an ExternalASTSource into an ExternalSemaSource.
+///
+/// Assumes shared ownership of the underlying source.
class ExternalASTSourceWrapper : public clang::ExternalSemaSource {
- ExternalASTSource *m_Source;
+ llvm::IntrusiveRefCntPtr<ExternalASTSource> m_Source;
public:
- ExternalASTSourceWrapper(ExternalASTSource *Source) : m_Source(Source) {
+ explicit ExternalASTSourceWrapper(ExternalASTSource *Source)
+ : m_Source(Source) {
assert(m_Source && "Can't wrap nullptr ExternalASTSource");
}
@@ -256,10 +259,18 @@ class SemaSourceWithPriorities : public clang::ExternalSemaSource {
/// Construct a SemaSourceWithPriorities with a 'high quality' source that
/// has the higher priority and a 'low quality' source that will be used
/// as a fallback.
- SemaSourceWithPriorities(clang::ExternalSemaSource &high_quality_source,
- clang::ExternalSemaSource &low_quality_source) {
- Sources.push_back(&high_quality_source);
- Sources.push_back(&low_quality_source);
+ ///
+ /// This class assumes shared ownership of the sources provided to it.
+ SemaSourceWithPriorities(clang::ExternalSemaSource *high_quality_source,
+ clang::ExternalSemaSource *low_quality_source) {
+ assert(high_quality_source);
+ assert(low_quality_source);
+
+ high_quality_source->Retain();
+ low_quality_source->Retain();
+
+ Sources.push_back(high_quality_source);
+ Sources.push_back(low_quality_source);
}
~SemaSourceWithPriorities() override;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index c441153d1efb05..d37787ebae26c3 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -1224,15 +1224,15 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
clang::ExternalASTSource *ast_source = decl_map->CreateProxy();
if (ast_context.getExternalSource()) {
- auto module_wrapper =
+ auto *module_wrapper =
new ExternalASTSourceWrapper(ast_context.getExternalSource());
- auto ast_source_wrapper = new ExternalASTSourceWrapper(ast_source);
+ auto *ast_source_wrapper = new ExternalASTSourceWrapper(ast_source);
- auto multiplexer =
- new SemaSourceWithPriorities(*module_wrapper, *ast_source_wrapper);
- IntrusiveRefCntPtr<ExternalASTSource> Source(multiplexer);
- ast_context.setExternalSource(Source);
+ auto *multiplexer =
+ new SemaSourceWithPriorities(module_wrapper, ast_source_wrapper);
+
+ ast_context.setExternalSource(multiplexer);
} else {
ast_context.setExternalSource(ast_source);
}
More information about the lldb-commits
mailing list