Allocate CodeCompletionString and all of its components in a

BumpPtrAllocator, rather than manually new/delete'ing them. This
optimization also allows us to avoid allocating memory for and copying
constant strings (e.g., "return", "class").

This also required embedding the priority and availability of results
within the code completion string, to avoid extra memory allocation
within libclang.

llvm-svn: 124673
This commit is contained in:
Douglas Gregor 2011-02-01 19:23:04 +00:00
parent 433c6180ab
commit b278aafbfb
7 changed files with 968 additions and 995 deletions

View File

@ -288,6 +288,12 @@ public:
}
private:
/// \brief Allocator used to store temporary code completion results.
llvm::BumpPtrAllocator CompletionAllocator;
/// \brief Allocator used to store cached code completions.
llvm::BumpPtrAllocator CachedCompletionAllocator;
/// \brief The set of cached code-completion results.
std::vector<CachedCodeCompletionResult> CachedCompletionResults;

View File

@ -17,8 +17,8 @@
#include "clang/AST/CanonicalType.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "clang-c/Index.h"
#include <memory>
#include <string>
namespace llvm {
@ -354,119 +354,149 @@ public:
Chunk() : Kind(CK_Text), Text(0) { }
Chunk(ChunkKind Kind, llvm::StringRef Text = "");
Chunk(ChunkKind Kind, const char *Text = "");
/// \brief Create a new text chunk.
static Chunk CreateText(llvm::StringRef Text);
static Chunk CreateText(const char *Text);
/// \brief Create a new optional chunk.
static Chunk CreateOptional(std::auto_ptr<CodeCompletionString> Optional);
static Chunk CreateOptional(CodeCompletionString *Optional);
/// \brief Create a new placeholder chunk.
static Chunk CreatePlaceholder(llvm::StringRef Placeholder);
static Chunk CreatePlaceholder(const char *Placeholder);
/// \brief Create a new informative chunk.
static Chunk CreateInformative(llvm::StringRef Informative);
static Chunk CreateInformative(const char *Informative);
/// \brief Create a new result type chunk.
static Chunk CreateResultType(llvm::StringRef ResultType);
static Chunk CreateResultType(const char *ResultType);
/// \brief Create a new current-parameter chunk.
static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter);
/// \brief Clone the given chunk.
Chunk Clone() const;
/// \brief Destroy this chunk, deallocating any memory it owns.
void Destroy();
static Chunk CreateCurrentParameter(const char *CurrentParameter);
};
private:
/// \brief The chunks stored in this string.
llvm::SmallVector<Chunk, 4> Chunks;
/// \brief The number of chunks stored in this string.
unsigned NumChunks;
/// \brief The priority of this code-completion string.
unsigned Priority : 30;
/// \brief The availability of this code-completion result.
CXAvailabilityKind Availability : 2;
CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT
CodeCompletionString &operator=(const CodeCompletionString &); // DITTO
CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
unsigned Priority, CXAvailabilityKind Availability);
~CodeCompletionString() { }
friend class CodeCompletionBuilder;
friend class CodeCompletionResult;
public:
CodeCompletionString() { }
~CodeCompletionString() { clear(); }
typedef const Chunk *iterator;
iterator begin() const { return reinterpret_cast<const Chunk *>(this + 1); }
iterator end() const { return begin() + NumChunks; }
bool empty() const { return NumChunks == 0; }
unsigned size() const { return NumChunks; }
typedef llvm::SmallVector<Chunk, 4>::const_iterator iterator;
iterator begin() const { return Chunks.begin(); }
iterator end() const { return Chunks.end(); }
bool empty() const { return Chunks.empty(); }
unsigned size() const { return Chunks.size(); }
void clear();
Chunk &operator[](unsigned I) {
assert(I < size() && "Chunk index out-of-range");
return Chunks[I];
}
const Chunk &operator[](unsigned I) const {
assert(I < size() && "Chunk index out-of-range");
return Chunks[I];
return begin()[I];
}
/// \brief Returns the text in the TypedText chunk.
const char *getTypedText() const;
/// \brief Retrieve the priority of this code completion result.
unsigned getPriority() const { return Priority; }
/// \brief Reteirve the availability of this code completion result.
unsigned getAvailability() const { return Availability; }
/// \brief Retrieve a string representation of the code completion string,
/// which is mainly useful for debugging.
std::string getAsString() const;
};
/// \brief A builder class used to construct new code-completion strings.
class CodeCompletionBuilder {
public:
typedef CodeCompletionString::Chunk Chunk;
private:
llvm::BumpPtrAllocator &Allocator;
unsigned Priority;
CXAvailabilityKind Availability;
/// \brief The chunks stored in this string.
llvm::SmallVector<Chunk, 4> Chunks;
public:
CodeCompletionBuilder(llvm::BumpPtrAllocator &Allocator)
: Allocator(Allocator), Priority(0), Availability(CXAvailability_Available){
}
CodeCompletionBuilder(llvm::BumpPtrAllocator &Allocator,
unsigned Priority, CXAvailabilityKind Availability)
: Allocator(Allocator), Priority(Priority), Availability(Availability) { }
/// \brief Retrieve the allocator into which the code completion
/// strings will be
llvm::BumpPtrAllocator &getAllocator() const { return Allocator; }
/// \brief Take the resulting completion string.
///
/// This operation can only be performed once.
CodeCompletionString *TakeString();
/// \brief Add a new typed-text chunk.
/// The text string will be copied.
void AddTypedTextChunk(llvm::StringRef Text) {
Chunks.push_back(Chunk(CK_TypedText, Text));
void AddTypedTextChunk(const char *Text) {
Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text));
}
/// \brief Add a new text chunk.
/// The text string will be copied.
void AddTextChunk(llvm::StringRef Text) {
void AddTextChunk(const char *Text) {
Chunks.push_back(Chunk::CreateText(Text));
}
/// \brief Add a new optional chunk.
void AddOptionalChunk(std::auto_ptr<CodeCompletionString> Optional) {
void AddOptionalChunk(CodeCompletionString *Optional) {
Chunks.push_back(Chunk::CreateOptional(Optional));
}
/// \brief Add a new placeholder chunk.
/// The placeholder text will be copied.
void AddPlaceholderChunk(llvm::StringRef Placeholder) {
void AddPlaceholderChunk(const char *Placeholder) {
Chunks.push_back(Chunk::CreatePlaceholder(Placeholder));
}
/// \brief Add a new informative chunk.
/// The text will be copied.
void AddInformativeChunk(llvm::StringRef Text) {
void AddInformativeChunk(const char *Text) {
Chunks.push_back(Chunk::CreateInformative(Text));
}
/// \brief Add a new result-type chunk.
/// The text will be copied.
void AddResultTypeChunk(llvm::StringRef ResultType) {
void AddResultTypeChunk(const char *ResultType) {
Chunks.push_back(Chunk::CreateResultType(ResultType));
}
/// \brief Add a new current-parameter chunk.
/// The text will be copied.
void AddCurrentParameterChunk(llvm::StringRef CurrentParameter) {
void AddCurrentParameterChunk(const char *CurrentParameter) {
Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter));
}
/// \brief Add a new chunk.
void AddChunk(Chunk C) { Chunks.push_back(C); }
/// \brief Returns the text in the TypedText chunk.
const char *getTypedText() const;
/// \brief Retrieve a string representation of the code completion string,
/// which is mainly useful for debugging.
std::string getAsString() const;
/// \brief Clone this code-completion string.
///
/// \param Result If non-NULL, points to an empty code-completion
/// result that will be given a cloned copy of
CodeCompletionString *Clone(CodeCompletionString *Result = 0) const;
};
/// \brief Captures a result of code completion.
class CodeCompletionResult {
public:
@ -597,13 +627,10 @@ public:
///
/// \param S The semantic analysis that created the result.
///
/// \param Result If non-NULL, the already-allocated, empty
/// code-completion string that will be populated with the
/// appropriate code completion string for this result.
/// \param Allocator The allocator that will be used to allocate the
/// string itself.
CodeCompletionString *CreateCodeCompletionString(Sema &S,
CodeCompletionString *Result = 0);
void Destroy();
llvm::BumpPtrAllocator &Allocator);
/// \brief Determine a base priority for the given declaration.
static unsigned getPriorityFromDecl(NamedDecl *ND);
@ -715,7 +742,7 @@ public:
/// signature of this overload candidate.
CodeCompletionString *CreateSignatureString(unsigned CurrentArg,
Sema &S,
CodeCompletionString *Result = 0) const;
llvm::BumpPtrAllocator &Allocator) const;
};
CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
@ -761,6 +788,10 @@ public:
OverloadCandidate *Candidates,
unsigned NumCandidates) { }
//@}
/// \brief Retrieve the allocator that will be used to allocate
/// code completion strings.
virtual llvm::BumpPtrAllocator &getAllocator() = 0;
};
/// \brief A simple code-completion consumer that prints the results it
@ -769,6 +800,8 @@ class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
/// \brief The raw output stream.
llvm::raw_ostream &OS;
llvm::BumpPtrAllocator Allocator;
public:
/// \brief Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
@ -787,6 +820,8 @@ public:
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates);
virtual llvm::BumpPtrAllocator &getAllocator() { return Allocator; }
};
} // end namespace clang

View File

@ -4909,7 +4909,7 @@ public:
MacroInfo *MacroInfo,
unsigned Argument);
void CodeCompleteNaturalLanguage();
void GatherGlobalCodeCompletions(
void GatherGlobalCodeCompletions(llvm::BumpPtrAllocator &Allocator,
llvm::SmallVectorImpl<CodeCompletionResult> &Results);
//@}

View File

@ -222,7 +222,7 @@ void ASTUnit::CacheCodeCompletionResults() {
// Gather the set of global code completions.
typedef CodeCompletionResult Result;
llvm::SmallVector<Result, 8> Results;
TheSema->GatherGlobalCodeCompletions(Results);
TheSema->GatherGlobalCodeCompletions(CachedCompletionAllocator, Results);
// Translate global code completions into cached completions.
llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
@ -232,7 +232,8 @@ void ASTUnit::CacheCodeCompletionResults() {
case Result::RK_Declaration: {
bool IsNestedNameSpecifier = false;
CachedCodeCompletionResult CachedResult;
CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
CachedCompletionAllocator);
CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
Ctx->getLangOptions(),
IsNestedNameSpecifier);
@ -294,7 +295,9 @@ void ASTUnit::CacheCodeCompletionResults() {
// nested-name-specifier but isn't already an option, create a
// nested-name-specifier completion.
Results[I].StartsNestedNameSpecifier = true;
CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
CachedResult.Completion
= Results[I].CreateCodeCompletionString(*TheSema,
CachedCompletionAllocator);
CachedResult.ShowInContexts = RemainingContexts;
CachedResult.Priority = CCP_NestedNameSpecifier;
CachedResult.TypeClass = STC_Void;
@ -313,7 +316,9 @@ void ASTUnit::CacheCodeCompletionResults() {
case Result::RK_Macro: {
CachedCodeCompletionResult CachedResult;
CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
CachedResult.Completion
= Results[I].CreateCodeCompletionString(*TheSema,
CachedCompletionAllocator);
CachedResult.ShowInContexts
= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
| (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
@ -337,7 +342,6 @@ void ASTUnit::CacheCodeCompletionResults() {
break;
}
}
Results[I].Destroy();
}
// Make a note of the state when we performed this caching.
@ -345,10 +349,9 @@ void ASTUnit::CacheCodeCompletionResults() {
}
void ASTUnit::ClearCachedCompletionResults() {
for (unsigned I = 0, N = CachedCompletionResults.size(); I != N; ++I)
delete CachedCompletionResults[I].Completion;
CachedCompletionResults.clear();
CachedCompletionTypes.clear();
CachedCompletionAllocator.Reset();
}
namespace {
@ -1657,6 +1660,10 @@ namespace {
unsigned NumCandidates) {
Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
}
virtual llvm::BumpPtrAllocator &getAllocator() {
return Next.getAllocator();
}
};
}
@ -1750,7 +1757,6 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
// Contains the set of names that are hidden by "local" completion results.
llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
llvm::SmallVector<CodeCompletionString *, 4> StringsToDestroy;
typedef CodeCompletionResult Result;
llvm::SmallVector<Result, 8> AllResults;
for (ASTUnit::cached_completion_iterator
@ -1809,11 +1815,12 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
// Create a new code-completion string that just contains the
// macro name, without its arguments.
Completion = new CodeCompletionString;
Completion->AddTypedTextChunk(C->Completion->getTypedText());
StringsToDestroy.push_back(Completion);
CodeCompletionBuilder Builder(getAllocator(), CCP_CodePattern,
C->Availability);
Builder.AddTypedTextChunk(C->Completion->getTypedText());
CursorKind = CXCursor_NotImplemented;
Priority = CCP_CodePattern;
Completion = Builder.TakeString();
}
AllResults.push_back(Result(Completion, Priority, CursorKind,
@ -1829,9 +1836,6 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
AllResults.size());
for (unsigned I = 0, N = StringsToDestroy.size(); I != N; ++I)
delete StringsToDestroy[I];
}

View File

@ -71,7 +71,7 @@ bool CodeCompletionContext::wantConstructorResults() const {
//===----------------------------------------------------------------------===//
// Code completion string implementation
//===----------------------------------------------------------------------===//
CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
: Kind(Kind), Text("")
{
switch (Kind) {
@ -80,13 +80,9 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
case CK_Placeholder:
case CK_Informative:
case CK_ResultType:
case CK_CurrentParameter: {
char *New = new char [Text.size() + 1];
std::memcpy(New, Text.data(), Text.size());
New[Text.size()] = '\0';
this->Text = New;
case CK_CurrentParameter:
this->Text = Text;
break;
}
case CK_Optional:
llvm_unreachable("Optional strings cannot be created from text");
@ -151,112 +147,48 @@ CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
}
CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateText(StringRef Text) {
CodeCompletionString::Chunk::CreateText(const char *Text) {
return Chunk(CK_Text, Text);
}
CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateOptional(
std::auto_ptr<CodeCompletionString> Optional) {
CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
Chunk Result;
Result.Kind = CK_Optional;
Result.Optional = Optional.release();
Result.Optional = Optional;
return Result;
}
CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
return Chunk(CK_Placeholder, Placeholder);
}
CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
return Chunk(CK_Informative, Informative);
}
CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) {
CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
return Chunk(CK_ResultType, ResultType);
}
CodeCompletionString::Chunk
CodeCompletionString::Chunk::CreateCurrentParameter(
StringRef CurrentParameter) {
const char *CurrentParameter) {
return Chunk(CK_CurrentParameter, CurrentParameter);
}
CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
switch (Kind) {
case CK_TypedText:
case CK_Text:
case CK_Placeholder:
case CK_Informative:
case CK_ResultType:
case CK_CurrentParameter:
case CK_LeftParen:
case CK_RightParen:
case CK_LeftBracket:
case CK_RightBracket:
case CK_LeftBrace:
case CK_RightBrace:
case CK_LeftAngle:
case CK_RightAngle:
case CK_Comma:
case CK_Colon:
case CK_SemiColon:
case CK_Equal:
case CK_HorizontalSpace:
case CK_VerticalSpace:
return Chunk(Kind, Text);
case CK_Optional: {
std::auto_ptr<CodeCompletionString> Opt(Optional->Clone());
return CreateOptional(Opt);
}
}
// Silence GCC warning.
return Chunk();
}
void
CodeCompletionString::Chunk::Destroy() {
switch (Kind) {
case CK_Optional:
delete Optional;
break;
case CK_TypedText:
case CK_Text:
case CK_Placeholder:
case CK_Informative:
case CK_ResultType:
case CK_CurrentParameter:
delete [] Text;
break;
case CK_LeftParen:
case CK_RightParen:
case CK_LeftBracket:
case CK_RightBracket:
case CK_LeftBrace:
case CK_RightBrace:
case CK_LeftAngle:
case CK_RightAngle:
case CK_Comma:
case CK_Colon:
case CK_SemiColon:
case CK_Equal:
case CK_HorizontalSpace:
case CK_VerticalSpace:
break;
}
}
void CodeCompletionString::clear() {
std::for_each(Chunks.begin(), Chunks.end(),
std::mem_fun_ref(&Chunk::Destroy));
Chunks.clear();
CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
unsigned NumChunks,
unsigned Priority,
CXAvailabilityKind Availability)
: NumChunks(NumChunks), Priority(Priority), Availability(Availability)
{
Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
for (unsigned I = 0; I != NumChunks; ++I)
StoredChunks[I] = Chunks[I];
}
std::string CodeCompletionString::getAsString() const {
@ -288,22 +220,17 @@ const char *CodeCompletionString::getTypedText() const {
return 0;
}
CodeCompletionString *
CodeCompletionString::Clone(CodeCompletionString *Result) const {
if (!Result)
Result = new CodeCompletionString;
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
Result->AddChunk(C->Clone());
CodeCompletionString *CodeCompletionBuilder::TakeString() {
void *Mem = Allocator.Allocate(
sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size(),
llvm::alignOf<CodeCompletionString>());
CodeCompletionString *Result
= new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
Priority, Availability);
Chunks.clear();
return Result;
}
void CodeCompletionResult::Destroy() {
if (Kind == RK_Pattern) {
delete Pattern;
Pattern = 0;
}
}
unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
if (!ND)
return CCP_Unlikely;
@ -383,9 +310,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
if (Results[I].Hidden)
OS << " (Hidden)";
if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef)) {
= Results[I].CreateCodeCompletionString(SemaRef, Allocator)) {
OS << " : " << CCS->getAsString();
delete CCS;
}
OS << '\n';
@ -398,9 +324,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
case CodeCompletionResult::RK_Macro: {
OS << Results[I].Macro->getName();
if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef)) {
= Results[I].CreateCodeCompletionString(SemaRef, Allocator)) {
OS << " : " << CCS->getAsString();
delete CCS;
}
OS << '\n';
break;
@ -422,9 +347,9 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
unsigned NumCandidates) {
for (unsigned I = 0; I != NumCandidates; ++I) {
if (CodeCompletionString *CCS
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
Allocator)) {
OS << "OVERLOAD: " << CCS->getAsString() << "\n";
delete CCS;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -45,31 +45,12 @@
using namespace clang;
using namespace clang::cxstring;
namespace {
/// \brief Stored representation of a completion string.
///
/// This is the representation behind a CXCompletionString.
class CXStoredCodeCompletionString : public CodeCompletionString {
unsigned Priority;
CXAvailabilityKind Availability;
public:
CXStoredCodeCompletionString(unsigned Priority,
CXAvailabilityKind Availability)
: Priority(Priority), Availability(Availability) { }
unsigned getPriority() const { return Priority; }
CXAvailabilityKind getAvailability() const { return Availability; }
};
}
extern "C" {
enum CXCompletionChunkKind
clang_getCompletionChunkKind(CXCompletionString completion_string,
unsigned chunk_number) {
CXStoredCodeCompletionString *CCStr
= (CXStoredCodeCompletionString *)completion_string;
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
if (!CCStr || chunk_number >= CCStr->size())
return CXCompletionChunk_Text;
@ -124,8 +105,7 @@ clang_getCompletionChunkKind(CXCompletionString completion_string,
CXString clang_getCompletionChunkText(CXCompletionString completion_string,
unsigned chunk_number) {
CXStoredCodeCompletionString *CCStr
= (CXStoredCodeCompletionString *)completion_string;
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
if (!CCStr || chunk_number >= CCStr->size())
return createCXString((const char*)0);
@ -165,8 +145,7 @@ CXString clang_getCompletionChunkText(CXCompletionString completion_string,
CXCompletionString
clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
unsigned chunk_number) {
CXStoredCodeCompletionString *CCStr
= (CXStoredCodeCompletionString *)completion_string;
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
if (!CCStr || chunk_number >= CCStr->size())
return 0;
@ -203,22 +182,20 @@ clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
}
unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
CXStoredCodeCompletionString *CCStr
= (CXStoredCodeCompletionString *)completion_string;
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
return CCStr? CCStr->size() : 0;
}
unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
CXStoredCodeCompletionString *CCStr
= (CXStoredCodeCompletionString *)completion_string;
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
}
enum CXAvailabilityKind
clang_getCompletionAvailability(CXCompletionString completion_string) {
CXStoredCodeCompletionString *CCStr
= (CXStoredCodeCompletionString *)completion_string;
return CCStr? CCStr->getAvailability() : CXAvailability_Available;
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
return CCStr? static_cast<CXAvailabilityKind>(CCStr->getAvailability())
: CXAvailability_Available;
}
/// \brief The CXCodeCompleteResults structure we allocate internally;
@ -251,6 +228,9 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
/// \brief Temporary buffers that will be deleted once we have finished with
/// the code-completion results.
llvm::SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
/// \brief Allocator used to store code completion results.
llvm::BumpPtrAllocator CodeCompletionAllocator;
};
/// \brief Tracks the number of code-completion result objects that are
@ -272,8 +252,6 @@ AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
}
AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
for (unsigned I = 0, N = NumResults; I != N; ++I)
delete (CXStoredCodeCompletionString *)Results[I].CompletionString;
delete [] Results;
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
@ -293,9 +271,8 @@ namespace {
class CaptureCompletionResults : public CodeCompleteConsumer {
AllocatedCXCodeCompleteResults &AllocatedResults;
llvm::SmallVector<CXCompletionResult, 16> StoredResults;
public:
explicit CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results)
CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results)
: CodeCompleteConsumer(true, false, true, false),
AllocatedResults(Results) { }
~CaptureCompletionResults() { Finish(); }
@ -306,10 +283,9 @@ namespace {
unsigned NumResults) {
StoredResults.reserve(StoredResults.size() + NumResults);
for (unsigned I = 0; I != NumResults; ++I) {
CXStoredCodeCompletionString *StoredCompletion
= new CXStoredCodeCompletionString(Results[I].Priority,
Results[I].Availability);
(void)Results[I].CreateCodeCompletionString(S, StoredCompletion);
CodeCompletionString *StoredCompletion
= Results[I].CreateCodeCompletionString(S,
AllocatedResults.CodeCompletionAllocator);
CXCompletionResult R;
R.CursorKind = Results[I].CursorKind;
@ -323,11 +299,9 @@ namespace {
unsigned NumCandidates) {
StoredResults.reserve(StoredResults.size() + NumCandidates);
for (unsigned I = 0; I != NumCandidates; ++I) {
// FIXME: Set priority, availability appropriately.
CXStoredCodeCompletionString *StoredCompletion
= new CXStoredCodeCompletionString(1, CXAvailability_Available);
(void)Candidates[I].CreateSignatureString(CurrentArg, S,
StoredCompletion);
CodeCompletionString *StoredCompletion
= Candidates[I].CreateSignatureString(CurrentArg, S,
AllocatedResults.CodeCompletionAllocator);
CXCompletionResult R;
R.CursorKind = CXCursor_NotImplemented;
@ -336,6 +310,10 @@ namespace {
}
}
virtual llvm::BumpPtrAllocator &getAllocator() {
return AllocatedResults.CodeCompletionAllocator;
}
private:
void Finish() {
AllocatedResults.Results = new CXCompletionResult [StoredResults.size()];
@ -596,10 +574,10 @@ namespace {
struct OrderCompletionResults {
bool operator()(const CXCompletionResult &XR,
const CXCompletionResult &YR) const {
CXStoredCodeCompletionString *X
= (CXStoredCodeCompletionString *)XR.CompletionString;
CXStoredCodeCompletionString *Y
= (CXStoredCodeCompletionString *)YR.CompletionString;
CodeCompletionString *X
= (CodeCompletionString *)XR.CompletionString;
CodeCompletionString *Y
= (CodeCompletionString *)YR.CompletionString;
llvm::SmallString<256> XBuffer;
llvm::StringRef XText = GetTypedName(X, XBuffer);