diff options
-rw-r--r-- | include/clang/Frontend/ASTUnit.h | 6 | ||||
-rw-r--r-- | include/clang/Sema/CodeCompleteConsumer.h | 157 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 32 | ||||
-rw-r--r-- | lib/Sema/CodeCompleteConsumer.cpp | 137 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 1553 | ||||
-rw-r--r-- | tools/libclang/CIndexCodeCompletion.cpp | 74 |
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 |