diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 0841480cf570..e93563311b85 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/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/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index a56fefc69f10..46f5b5a48e74 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/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/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp index 705c62c6fe04..292719bebdae 100644 --- a/clang/tools/libclang/CIndexCodeCompletion.cpp +++ b/clang/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();