forked from OSchip/llvm-project
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:
parent
1728c232d5
commit
162b712d38
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue