aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Frontend/ASTUnit.h6
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h157
-rw-r--r--include/clang/Sema/Sema.h2
-rw-r--r--lib/Frontend/ASTUnit.cpp32
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp137
-rw-r--r--lib/Sema/SemaCodeComplete.cpp1553
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp74
7 files changed, 967 insertions, 994 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 12555ab1af..6ee3e85fef 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -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;
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 5cdcc27b67..9daefd72a5 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -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
-public:
- CodeCompletionString() { }
- ~CodeCompletionString() { clear(); }
+ CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
+ unsigned Priority, CXAvailabilityKind Availability);
+ ~CodeCompletionString() { }
- 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();
+ friend class CodeCompletionBuilder;
+ friend class CodeCompletionResult;
- Chunk &operator[](unsigned I) {
+public:
+ 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; }
+
+ 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;
- const Chunk &operator[](unsigned I) const {
- assert(I < size() && "Chunk index out-of-range");
- return Chunks[I];
+ /// \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
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 908d1a1ca6..9d04421715 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4909,7 +4909,7 @@ public:
MacroInfo *MacroInfo,
unsigned Argument);
void CodeCompleteNaturalLanguage();
- void GatherGlobalCodeCompletions(
+ void GatherGlobalCodeCompletions(llvm::BumpPtrAllocator &Allocator,
llvm::SmallVectorImpl<CodeCompletionResult> &Results);
//@}
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 9116d0ed17..5617df6881 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -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];
}
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index ee6fb3bf0e..ddfe8b0b17 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -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;
}
}
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 50ea6cb0b5..051603ce6d 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -117,6 +117,9 @@ namespace {
/// \brief The semantic analysis object for which results are being
/// produced.
Sema &SemaRef;
+
+ /// \brief The allocator used to allocate new code-completion strings.
+ llvm::BumpPtrAllocator &Allocator;
/// \brief If non-NULL, a filter function used to remove any code-completion
/// results that are not desirable.
@@ -159,11 +162,11 @@ namespace {
void MaybeAddConstructorResults(Result R);
public:
- explicit ResultBuilder(Sema &SemaRef,
+ explicit ResultBuilder(Sema &SemaRef, llvm::BumpPtrAllocator &Allocator,
const CodeCompletionContext &CompletionContext,
LookupFilter Filter = 0)
- : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false),
- HasObjectTypeQualifiers(false),
+ : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
+ AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
CompletionContext(CompletionContext),
ObjCImplementation(0)
{
@@ -243,6 +246,9 @@ namespace {
/// code completion results.
Sema &getSema() const { return SemaRef; }
+ /// \brief Retrieve the allocator used to allocate code completion strings.
+ llvm::BumpPtrAllocator &getAllocator() const { return Allocator; }
+
/// \brief Determine whether the given declaration is at all interesting
/// as a code-completion result.
///
@@ -1189,6 +1195,7 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Results.AddResult(Result("restrict", CCP_Type));
}
+ CodeCompletionBuilder Builder(Results.getAllocator());
if (LangOpts.CPlusPlus) {
// C++-specific
Results.AddResult(Result("bool", CCP_Type +
@@ -1197,25 +1204,23 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Results.AddResult(Result("wchar_t", CCP_Type));
// typename qualified-id
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("typename");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("qualifier");
- Pattern->AddTextChunk("::");
- Pattern->AddPlaceholderChunk("name");
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("typename");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("qualifier");
+ Builder.AddTextChunk("::");
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(Result(Builder.TakeString()));
if (LangOpts.CPlusPlus0x) {
Results.AddResult(Result("auto", CCP_Type));
Results.AddResult(Result("char16_t", CCP_Type));
Results.AddResult(Result("char32_t", CCP_Type));
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("decltype");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("decltype");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("expression");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
}
}
@@ -1226,18 +1231,16 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
// Results.AddResult(Result("_Decimal64"));
// Results.AddResult(Result("_Decimal128"));
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("typeof");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("expression");
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("typeof");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Builder.TakeString()));
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("typeof");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("type");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("typeof");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
}
}
@@ -1301,13 +1304,13 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts,
static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
static void AddTypedefResult(ResultBuilder &Results) {
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("typedef");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("type");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("name");
- Results.AddResult(CodeCompletionResult(Pattern));
+ CodeCompletionBuilder Builder(Results.getAllocator());
+ Builder.AddTypedTextChunk("typedef");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("type");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
@@ -1344,58 +1347,53 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Scope *S,
Sema &SemaRef,
ResultBuilder &Results) {
+ CodeCompletionBuilder Builder(Results.getAllocator());
+
typedef CodeCompletionResult Result;
switch (CCC) {
case Sema::PCC_Namespace:
if (SemaRef.getLangOptions().CPlusPlus) {
- CodeCompletionString *Pattern = 0;
-
if (Results.includeCodePatterns()) {
// namespace <identifier> { declarations }
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("namespace");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("identifier");
- Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
- Pattern->AddPlaceholderChunk("declarations");
- Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
- Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("namespace");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("identifier");
+ Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
+ Builder.AddPlaceholderChunk("declarations");
+ Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Builder.AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Builder.TakeString()));
}
// namespace identifier = identifier ;
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("namespace");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("name");
- Pattern->AddChunk(CodeCompletionString::CK_Equal);
- Pattern->AddPlaceholderChunk("namespace");
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("namespace");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("name");
+ Builder.AddChunk(CodeCompletionString::CK_Equal);
+ Builder.AddPlaceholderChunk("namespace");
+ Results.AddResult(Result(Builder.TakeString()));
// Using directives
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("using");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddTextChunk("namespace");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("identifier");
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("using");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("namespace");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("identifier");
+ Results.AddResult(Result(Builder.TakeString()));
// asm(string-literal)
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("asm");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("string-literal");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("asm");
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+ Builder.AddPlaceholderChunk("string-literal");
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Builder.TakeString()));
if (Results.includeCodePatterns()) {
// Explicit template instantiation
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("template");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("declaration");
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("template");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("declaration");
+ Results.AddResult(Result(Builder.TakeString()));
}
}
@@ -1408,47 +1406,42 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
case Sema::PCC_Class:
if (SemaRef.getLangOptions().CPlusPlus) {
// Using declaration
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("using");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("qualifier");
- Pattern->AddTextChunk("::");
- Pattern->AddPlaceholderChunk("name");
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("using");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("qualifier");
+ Builder.AddTextChunk("::");
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(Result(Builder.TakeString()));
// using typename qualifier::name (only in a dependent context)
if (SemaRef.CurContext->isDependentContext()) {
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("using");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddTextChunk("typename");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("qualifier");
- Pattern->AddTextChunk("::");
- Pattern->AddPlaceholderChunk("name");
- Results.AddResult(Result(Pattern));
+ Builder.AddTypedTextChunk("using");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddTextChunk("typename");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("qualifier");
+ Builder.AddTextChunk("::");
+ Builder.AddPlaceholderChunk("name");
+ Results.AddResult(Result(Builder.TakeS