[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