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
<rdar://problem/8997369>.

llvm-svn: 125678
This commit is contained in:
Douglas Gregor 2011-02-16 19:08:06 +00:00
parent 1728c232d5
commit 162b712d38
3 changed files with 33 additions and 7 deletions

View File

@ -54,6 +54,14 @@ class TargetInfo;
using namespace idx; using namespace idx;
/// \brief Allocator for a cached set of global code completions.
class GlobalCodeCompletionAllocator
: public CodeCompletionAllocator,
public llvm::RefCountedBase<GlobalCodeCompletionAllocator>
{
};
/// \brief Utility class for loading a ASTContext from an AST file. /// \brief Utility class for loading a ASTContext from an AST file.
/// ///
class ASTUnit { class ASTUnit {
@ -287,9 +295,16 @@ public:
return CachedCompletionTypes; return CachedCompletionTypes;
} }
/// \brief Retrieve the allocator used to cache global code completions.
llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
getCachedCompletionAllocator() {
return CachedCompletionAllocator;
}
private: private:
/// \brief Allocator used to store cached code completions. /// \brief Allocator used to store cached code completions.
CodeCompletionAllocator CachedCompletionAllocator; llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
CachedCompletionAllocator;
/// \brief The set of cached code-completion results. /// \brief The set of cached code-completion results.
std::vector<CachedCodeCompletionResult> CachedCompletionResults; std::vector<CachedCodeCompletionResult> CachedCompletionResults;

View File

@ -224,7 +224,8 @@ void ASTUnit::CacheCodeCompletionResults() {
// Gather the set of global code completions. // Gather the set of global code completions.
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
llvm::SmallVector<Result, 8> Results; llvm::SmallVector<Result, 8> Results;
TheSema->GatherGlobalCodeCompletions(CachedCompletionAllocator, Results); CachedCompletionAllocator = new GlobalCodeCompletionAllocator;
TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, Results);
// Translate global code completions into cached completions. // Translate global code completions into cached completions.
llvm::DenseMap<CanQualType, unsigned> CompletionTypes; llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
@ -235,7 +236,7 @@ void ASTUnit::CacheCodeCompletionResults() {
bool IsNestedNameSpecifier = false; bool IsNestedNameSpecifier = false;
CachedCodeCompletionResult CachedResult; CachedCodeCompletionResult CachedResult;
CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema, CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
CachedCompletionAllocator); *CachedCompletionAllocator);
CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration, CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
Ctx->getLangOptions(), Ctx->getLangOptions(),
IsNestedNameSpecifier); IsNestedNameSpecifier);
@ -299,7 +300,7 @@ void ASTUnit::CacheCodeCompletionResults() {
Results[I].StartsNestedNameSpecifier = true; Results[I].StartsNestedNameSpecifier = true;
CachedResult.Completion CachedResult.Completion
= Results[I].CreateCodeCompletionString(*TheSema, = Results[I].CreateCodeCompletionString(*TheSema,
CachedCompletionAllocator); *CachedCompletionAllocator);
CachedResult.ShowInContexts = RemainingContexts; CachedResult.ShowInContexts = RemainingContexts;
CachedResult.Priority = CCP_NestedNameSpecifier; CachedResult.Priority = CCP_NestedNameSpecifier;
CachedResult.TypeClass = STC_Void; CachedResult.TypeClass = STC_Void;
@ -320,7 +321,7 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedCodeCompletionResult CachedResult; CachedCodeCompletionResult CachedResult;
CachedResult.Completion CachedResult.Completion
= Results[I].CreateCodeCompletionString(*TheSema, = Results[I].CreateCodeCompletionString(*TheSema,
CachedCompletionAllocator); *CachedCompletionAllocator);
CachedResult.ShowInContexts CachedResult.ShowInContexts
= (1 << (CodeCompletionContext::CCC_TopLevel - 1)) = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
| (1 << (CodeCompletionContext::CCC_ObjCInterface - 1)) | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
@ -353,7 +354,7 @@ void ASTUnit::CacheCodeCompletionResults() {
void ASTUnit::ClearCachedCompletionResults() { void ASTUnit::ClearCachedCompletionResults() {
CachedCompletionResults.clear(); CachedCompletionResults.clear();
CachedCompletionTypes.clear(); CachedCompletionTypes.clear();
CachedCompletionAllocator.Reset(); CachedCompletionAllocator = 0;
} }
namespace { namespace {

View File

@ -229,6 +229,10 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
/// the code-completion results. /// the code-completion results.
llvm::SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers; llvm::SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
/// \brief Allocator used to store globally cached code-completion results.
llvm::IntrusiveRefCntPtr<clang::GlobalCodeCompletionAllocator>
CachedCompletionAllocator;
/// \brief Allocator used to store code completion results. /// \brief Allocator used to store code completion results.
clang::CodeCompletionAllocator CodeCompletionAllocator; clang::CodeCompletionAllocator CodeCompletionAllocator;
}; };
@ -379,7 +383,7 @@ void clang_codeCompleteAt_Impl(void *UserData) {
AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults; AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
Results->Results = 0; Results->Results = 0;
Results->NumResults = 0; Results->NumResults = 0;
// Create a code-completion consumer to capture the results. // Create a code-completion consumer to capture the results.
CaptureCompletionResults Capture(*Results); CaptureCompletionResults Capture(*Results);
@ -392,6 +396,12 @@ void clang_codeCompleteAt_Impl(void *UserData) {
*Results->Diag, Results->LangOpts, Results->SourceMgr, *Results->Diag, Results->LangOpts, Results->SourceMgr,
Results->FileMgr, Results->Diagnostics, Results->FileMgr, Results->Diagnostics,
Results->TemporaryBuffers); 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();