From: Douglas Gregor Date: Wed, 16 Feb 2011 19:08:06 +0000 (+0000) Subject: Teach the CXCodeCompleteResults results structure, which stores X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48601b32321496b07a18fb6631f8563275d8c5fb;p=clang Teach the CXCodeCompleteResults results structure, which stores code-completion results accessed via libclang, to extend the lifetime of the allocator used for cached global code-completion results at least until these completion results are destroyed. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125678 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 0841480cf5..e93563311b 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -54,6 +54,14 @@ class TargetInfo; using namespace idx; +/// \brief Allocator for a cached set of global code completions. +class GlobalCodeCompletionAllocator + : public CodeCompletionAllocator, + public llvm::RefCountedBase +{ + +}; + /// \brief Utility class for loading a ASTContext from an AST file. /// class ASTUnit { @@ -287,9 +295,16 @@ public: return CachedCompletionTypes; } + /// \brief Retrieve the allocator used to cache global code completions. + llvm::IntrusiveRefCntPtr + getCachedCompletionAllocator() { + return CachedCompletionAllocator; + } + private: /// \brief Allocator used to store cached code completions. - CodeCompletionAllocator CachedCompletionAllocator; + llvm::IntrusiveRefCntPtr + CachedCompletionAllocator; /// \brief The set of cached code-completion results. std::vector CachedCompletionResults; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index a56fefc69f..46f5b5a48e 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -224,7 +224,8 @@ void ASTUnit::CacheCodeCompletionResults() { // Gather the set of global code completions. typedef CodeCompletionResult Result; llvm::SmallVector Results; - TheSema->GatherGlobalCodeCompletions(CachedCompletionAllocator, Results); + CachedCompletionAllocator = new GlobalCodeCompletionAllocator; + TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, Results); // Translate global code completions into cached completions. llvm::DenseMap CompletionTypes; @@ -235,7 +236,7 @@ void ASTUnit::CacheCodeCompletionResults() { bool IsNestedNameSpecifier = false; CachedCodeCompletionResult CachedResult; CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema, - CachedCompletionAllocator); + *CachedCompletionAllocator); CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration, Ctx->getLangOptions(), IsNestedNameSpecifier); @@ -299,7 +300,7 @@ void ASTUnit::CacheCodeCompletionResults() { Results[I].StartsNestedNameSpecifier = true; CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema, - CachedCompletionAllocator); + *CachedCompletionAllocator); CachedResult.ShowInContexts = RemainingContexts; CachedResult.Priority = CCP_NestedNameSpecifier; CachedResult.TypeClass = STC_Void; @@ -320,7 +321,7 @@ void ASTUnit::CacheCodeCompletionResults() { CachedCodeCompletionResult CachedResult; CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema, - CachedCompletionAllocator); + *CachedCompletionAllocator); CachedResult.ShowInContexts = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1)) @@ -353,7 +354,7 @@ void ASTUnit::CacheCodeCompletionResults() { void ASTUnit::ClearCachedCompletionResults() { CachedCompletionResults.clear(); CachedCompletionTypes.clear(); - CachedCompletionAllocator.Reset(); + CachedCompletionAllocator = 0; } namespace { diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index 705c62c6fe..292719bebd 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -229,6 +229,10 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { /// the code-completion results. llvm::SmallVector TemporaryBuffers; + /// \brief Allocator used to store globally cached code-completion results. + llvm::IntrusiveRefCntPtr + CachedCompletionAllocator; + /// \brief Allocator used to store code completion results. clang::CodeCompletionAllocator CodeCompletionAllocator; }; @@ -379,7 +383,7 @@ void clang_codeCompleteAt_Impl(void *UserData) { AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults; Results->Results = 0; Results->NumResults = 0; - + // Create a code-completion consumer to capture the results. CaptureCompletionResults Capture(*Results); @@ -392,6 +396,12 @@ void clang_codeCompleteAt_Impl(void *UserData) { *Results->Diag, Results->LangOpts, Results->SourceMgr, Results->FileMgr, Results->Diagnostics, Results->TemporaryBuffers); + + // Keep a reference to the allocator used for cached global completions, so + // that we can be sure that the memory used by our code completion strings + // doesn't get freed due to subsequent reparses (while the code completion + // results are still active). + Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator();