diff options
Diffstat (limited to 'lib/Sema/SemaCodeComplete.cpp')
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 3022 |
1 files changed, 1698 insertions, 1324 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 30af826ef6cc..d9f007a46da5 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -10,6 +10,8 @@ // This file defines the code-completion semantic actions. // //===----------------------------------------------------------------------===// +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" @@ -32,6 +34,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Path.h" #include <list> #include <map> #include <vector> @@ -40,315 +44,309 @@ using namespace clang; using namespace sema; namespace { - /// A container of code-completion results. - class ResultBuilder { - public: - /// The type of a name-lookup filter, which can be provided to the - /// name-lookup routines to specify which declarations should be included in - /// the result set (when it returns true) and which declarations should be - /// filtered out (returns false). - typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; - - typedef CodeCompletionResult Result; +/// A container of code-completion results. +class ResultBuilder { +public: + /// The type of a name-lookup filter, which can be provided to the + /// name-lookup routines to specify which declarations should be included in + /// the result set (when it returns true) and which declarations should be + /// filtered out (returns false). + typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; - private: - /// The actual results we have found. - std::vector<Result> Results; + typedef CodeCompletionResult Result; - /// A record of all of the declarations we have found and placed - /// into the result set, used to ensure that no declaration ever gets into - /// the result set twice. - llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound; +private: + /// The actual results we have found. + std::vector<Result> Results; - typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; + /// A record of all of the declarations we have found and placed + /// into the result set, used to ensure that no declaration ever gets into + /// the result set twice. + llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound; - /// An entry in the shadow map, which is optimized to store - /// a single (declaration, index) mapping (the common case) but - /// can also store a list of (declaration, index) mappings. - class ShadowMapEntry { - typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector; + typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; - /// Contains either the solitary NamedDecl * or a vector - /// of (declaration, index) pairs. - llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector; + /// An entry in the shadow map, which is optimized to store + /// a single (declaration, index) mapping (the common case) but + /// can also store a list of (declaration, index) mappings. + class ShadowMapEntry { + typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector; - /// When the entry contains a single declaration, this is - /// the index associated with that entry. - unsigned SingleDeclIndex; + /// Contains either the solitary NamedDecl * or a vector + /// of (declaration, index) pairs. + llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector; - public: - ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { } + /// When the entry contains a single declaration, this is + /// the index associated with that entry. + unsigned SingleDeclIndex; - void Add(const NamedDecl *ND, unsigned Index) { - if (DeclOrVector.isNull()) { - // 0 - > 1 elements: just set the single element information. - DeclOrVector = ND; - SingleDeclIndex = Index; - return; - } + public: + ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {} - if (const NamedDecl *PrevND = - DeclOrVector.dyn_cast<const NamedDecl *>()) { - // 1 -> 2 elements: create the vector of results and push in the - // existing declaration. - DeclIndexPairVector *Vec = new DeclIndexPairVector; - Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); - DeclOrVector = Vec; - } + void Add(const NamedDecl *ND, unsigned Index) { + if (DeclOrVector.isNull()) { + // 0 - > 1 elements: just set the single element information. + DeclOrVector = ND; + SingleDeclIndex = Index; + return; + } - // Add the new element to the end of the vector. - DeclOrVector.get<DeclIndexPairVector*>()->push_back( - DeclIndexPair(ND, Index)); + if (const NamedDecl *PrevND = + DeclOrVector.dyn_cast<const NamedDecl *>()) { + // 1 -> 2 elements: create the vector of results and push in the + // existing declaration. + DeclIndexPairVector *Vec = new DeclIndexPairVector; + Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); + DeclOrVector = Vec; } - void Destroy() { - if (DeclIndexPairVector *Vec - = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { - delete Vec; - DeclOrVector = ((NamedDecl *)nullptr); - } + // Add the new element to the end of the vector. + DeclOrVector.get<DeclIndexPairVector *>()->push_back( + DeclIndexPair(ND, Index)); + } + + void Destroy() { + if (DeclIndexPairVector *Vec = + DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { + delete Vec; + DeclOrVector = ((NamedDecl *)nullptr); } + } - // Iteration. - class iterator; - iterator begin() const; - iterator end() const; - }; + // Iteration. + class iterator; + iterator begin() const; + iterator end() const; + }; - /// A mapping from declaration names to the declarations that have - /// this name within a particular scope and their index within the list of - /// results. - typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; + /// A mapping from declaration names to the declarations that have + /// this name within a particular scope and their index within the list of + /// results. + typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; - /// The semantic analysis object for which results are being - /// produced. - Sema &SemaRef; + /// The semantic analysis object for which results are being + /// produced. + Sema &SemaRef; - /// The allocator used to allocate new code-completion strings. - CodeCompletionAllocator &Allocator; + /// The allocator used to allocate new code-completion strings. + CodeCompletionAllocator &Allocator; - CodeCompletionTUInfo &CCTUInfo; + CodeCompletionTUInfo &CCTUInfo; - /// If non-NULL, a filter function used to remove any code-completion - /// results that are not desirable. - LookupFilter Filter; + /// If non-NULL, a filter function used to remove any code-completion + /// results that are not desirable. + LookupFilter Filter; - /// Whether we should allow declarations as - /// nested-name-specifiers that would otherwise be filtered out. - bool AllowNestedNameSpecifiers; + /// Whether we should allow declarations as + /// nested-name-specifiers that would otherwise be filtered out. + bool AllowNestedNameSpecifiers; - /// If set, the type that we would prefer our resulting value - /// declarations to have. - /// - /// Closely matching the preferred type gives a boost to a result's - /// priority. - CanQualType PreferredType; + /// If set, the type that we would prefer our resulting value + /// declarations to have. + /// + /// Closely matching the preferred type gives a boost to a result's + /// priority. + CanQualType PreferredType; - /// A list of shadow maps, which is used to model name hiding at - /// different levels of, e.g., the inheritance hierarchy. - std::list<ShadowMap> ShadowMaps; + /// A list of shadow maps, which is used to model name hiding at + /// different levels of, e.g., the inheritance hierarchy. + std::list<ShadowMap> ShadowMaps; - /// If we're potentially referring to a C++ member function, the set - /// of qualifiers applied to the object type. - Qualifiers ObjectTypeQualifiers; + /// If we're potentially referring to a C++ member function, the set + /// of qualifiers applied to the object type. + Qualifiers ObjectTypeQualifiers; - /// Whether the \p ObjectTypeQualifiers field is active. - bool HasObjectTypeQualifiers; + /// Whether the \p ObjectTypeQualifiers field is active. + bool HasObjectTypeQualifiers; - /// The selector that we prefer. - Selector PreferredSelector; + /// The selector that we prefer. + Selector PreferredSelector; - /// The completion context in which we are gathering results. - CodeCompletionContext CompletionContext; + /// The completion context in which we are gathering results. + CodeCompletionContext CompletionContext; - /// If we are in an instance method definition, the \@implementation - /// object. - ObjCImplementationDecl *ObjCImplementation; + /// If we are in an instance method definition, the \@implementation + /// object. + ObjCImplementationDecl *ObjCImplementation; - void AdjustResultPriorityForDecl(Result &R); + void AdjustResultPriorityForDecl(Result &R); - void MaybeAddConstructorResults(Result R); + void MaybeAddConstructorResults(Result R); - public: - explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - const CodeCompletionContext &CompletionContext, - LookupFilter Filter = nullptr) +public: + explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + const CodeCompletionContext &CompletionContext, + LookupFilter Filter = nullptr) : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), - Filter(Filter), - AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), - CompletionContext(CompletionContext), - ObjCImplementation(nullptr) - { - // If this is an Objective-C instance method definition, dig out the - // corresponding implementation. - switch (CompletionContext.getKind()) { - case CodeCompletionContext::CCC_Expression: - case CodeCompletionContext::CCC_ObjCMessageReceiver: - case CodeCompletionContext::CCC_ParenthesizedExpression: - case CodeCompletionContext::CCC_Statement: - case CodeCompletionContext::CCC_Recovery: - if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) - if (Method->isInstanceMethod()) - if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) - ObjCImplementation = Interface->getImplementation(); - break; + Filter(Filter), AllowNestedNameSpecifiers(false), + HasObjectTypeQualifiers(false), CompletionContext(CompletionContext), + ObjCImplementation(nullptr) { + // If this is an Objective-C instance method definition, dig out the + // corresponding implementation. + switch (CompletionContext.getKind()) { + case CodeCompletionContext::CCC_Expression: + case CodeCompletionContext::CCC_ObjCMessageReceiver: + case CodeCompletionContext::CCC_ParenthesizedExpression: + case CodeCompletionContext::CCC_Statement: + case CodeCompletionContext::CCC_Recovery: + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) + if (Method->isInstanceMethod()) + if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) + ObjCImplementation = Interface->getImplementation(); + break; - default: - break; - } - } - - /// Determine the priority for a reference to the given declaration. - unsigned getBasePriority(const NamedDecl *D); - - /// Whether we should include code patterns in the completion - /// results. - bool includeCodePatterns() const { - return SemaRef.CodeCompleter && - SemaRef.CodeCompleter->includeCodePatterns(); - } - - /// Set the filter used for code-completion results. - void setFilter(LookupFilter Filter) { - this->Filter = Filter; - } - - Result *data() { return Results.empty()? nullptr : &Results.front(); } - unsigned size() const { return Results.size(); } - bool empty() const { return Results.empty(); } - - /// Specify the preferred type. - void setPreferredType(QualType T) { - PreferredType = SemaRef.Context.getCanonicalType(T); + default: + break; } + } - /// Set the cv-qualifiers on the object type, for us in filtering - /// calls to member functions. - /// - /// When there are qualifiers in this set, they will be used to filter - /// out member functions that aren't available (because there will be a - /// cv-qualifier mismatch) or prefer functions with an exact qualifier - /// match. - void setObjectTypeQualifiers(Qualifiers Quals) { - ObjectTypeQualifiers = Quals; - HasObjectTypeQualifiers = true; - } - - /// Set the preferred selector. - /// - /// When an Objective-C method declaration result is added, and that - /// method's selector matches this preferred selector, we give that method - /// a slight priority boost. - void setPreferredSelector(Selector Sel) { - PreferredSelector = Sel; - } - - /// Retrieve the code-completion context for which results are - /// being collected. - const CodeCompletionContext &getCompletionContext() const { - return CompletionContext; - } - - /// Specify whether nested-name-specifiers are allowed. - void allowNestedNameSpecifiers(bool Allow = true) { - AllowNestedNameSpecifiers = Allow; - } - - /// Return the semantic analysis object for which we are collecting - /// code completion results. - Sema &getSema() const { return SemaRef; } - - /// Retrieve the allocator used to allocate code completion strings. - CodeCompletionAllocator &getAllocator() const { return Allocator; } - - CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } - - /// Determine whether the given declaration is at all interesting - /// as a code-completion result. - /// - /// \param ND the declaration that we are inspecting. - /// - /// \param AsNestedNameSpecifier will be set true if this declaration is - /// only interesting when it is a nested-name-specifier. - bool isInterestingDecl(const NamedDecl *ND, - bool &AsNestedNameSpecifier) const; - - /// Check whether the result is hidden by the Hiding declaration. - /// - /// \returns true if the result is hidden and cannot be found, false if - /// the hidden result could still be found. When false, \p R may be - /// modified to describe how the result can be found (e.g., via extra - /// qualification). - bool CheckHiddenResult(Result &R, DeclContext *CurContext, - const NamedDecl *Hiding); - - /// Add a new result to this result set (if it isn't already in one - /// of the shadow maps), or replace an existing result (for, e.g., a - /// redeclaration). - /// - /// \param R the result to add (if it is unique). - /// - /// \param CurContext the context in which this result will be named. - void MaybeAddResult(Result R, DeclContext *CurContext = nullptr); - - /// Add a new result to this result set, where we already know - /// the hiding declaration (if any). - /// - /// \param R the result to add (if it is unique). - /// - /// \param CurContext the context in which this result will be named. - /// - /// \param Hiding the declaration that hides the result. - /// - /// \param InBaseClass whether the result was found in a base - /// class of the searched context. - void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, - bool InBaseClass); - - /// Add a new non-declaration result to this result set. - void AddResult(Result R); - - /// Enter into a new scope. - void EnterNewScope(); - - /// Exit from the current scope. - void ExitScope(); - - /// Ignore this declaration, if it is seen again. - void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } - - /// Add a visited context. - void addVisitedContext(DeclContext *Ctx) { - CompletionContext.addVisitedContext(Ctx); - } - - /// \name Name lookup predicates - /// - /// These predicates can be passed to the name lookup functions to filter the - /// results of name lookup. All of the predicates have the same type, so that - /// - //@{ - bool IsOrdinaryName(const NamedDecl *ND) const; - bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; - bool IsIntegralConstantValue(const NamedDecl *ND) const; - bool IsOrdinaryNonValueName(const NamedDecl *ND) const; - bool IsNestedNameSpecifier(const NamedDecl *ND) const; - bool IsEnum(const NamedDecl *ND) const; - bool IsClassOrStruct(const NamedDecl *ND) const; - bool IsUnion(const NamedDecl *ND) const; - bool IsNamespace(const NamedDecl *ND) const; - bool IsNamespaceOrAlias(const NamedDecl *ND) const; - bool IsType(const NamedDecl *ND) const; - bool IsMember(const NamedDecl *ND) const; - bool IsObjCIvar(const NamedDecl *ND) const; - bool IsObjCMessageReceiver(const NamedDecl *ND) const; - bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; - bool IsObjCCollection(const NamedDecl *ND) const; - bool IsImpossibleToSatisfy(const NamedDecl *ND) const; - //@} - }; -} + /// Determine the priority for a reference to the given declaration. + unsigned getBasePriority(const NamedDecl *D); + + /// Whether we should include code patterns in the completion + /// results. + bool includeCodePatterns() const { + return SemaRef.CodeCompleter && + SemaRef.CodeCompleter->includeCodePatterns(); + } + + /// Set the filter used for code-completion results. + void setFilter(LookupFilter Filter) { this->Filter = Filter; } + + Result *data() { return Results.empty() ? nullptr : &Results.front(); } + unsigned size() const { return Results.size(); } + bool empty() const { return Results.empty(); } + + /// Specify the preferred type. + void setPreferredType(QualType T) { + PreferredType = SemaRef.Context.getCanonicalType(T); + } + + /// Set the cv-qualifiers on the object type, for us in filtering + /// calls to member functions. + /// + /// When there are qualifiers in this set, they will be used to filter + /// out member functions that aren't available (because there will be a + /// cv-qualifier mismatch) or prefer functions with an exact qualifier + /// match. + void setObjectTypeQualifiers(Qualifiers Quals) { + ObjectTypeQualifiers = Quals; + HasObjectTypeQualifiers = true; + } + + /// Set the preferred selector. + /// + /// When an Objective-C method declaration result is added, and that + /// method's selector matches this preferred selector, we give that method + /// a slight priority boost. + void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; } + + /// Retrieve the code-completion context for which results are + /// being collected. + const CodeCompletionContext &getCompletionContext() const { + return CompletionContext; + } + + /// Specify whether nested-name-specifiers are allowed. + void allowNestedNameSpecifiers(bool Allow = true) { + AllowNestedNameSpecifiers = Allow; + } + + /// Return the semantic analysis object for which we are collecting + /// code completion results. + Sema &getSema() const { return SemaRef; } + + /// Retrieve the allocator used to allocate code completion strings. + CodeCompletionAllocator &getAllocator() const { return Allocator; } + + CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } + + /// Determine whether the given declaration is at all interesting + /// as a code-completion result. + /// + /// \param ND the declaration that we are inspecting. + /// + /// \param AsNestedNameSpecifier will be set true if this declaration is + /// only interesting when it is a nested-name-specifier. + bool isInterestingDecl(const NamedDecl *ND, + bool &AsNestedNameSpecifier) const; + + /// Check whether the result is hidden by the Hiding declaration. + /// + /// \returns true if the result is hidden and cannot be found, false if + /// the hidden result could still be found. When false, \p R may be + /// modified to describe how the result can be found (e.g., via extra + /// qualification). + bool CheckHiddenResult(Result &R, DeclContext *CurContext, + const NamedDecl *Hiding); + + /// Add a new result to this result set (if it isn't already in one + /// of the shadow maps), or replace an existing result (for, e.g., a + /// redeclaration). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + void MaybeAddResult(Result R, DeclContext *CurContext = nullptr); + + /// Add a new result to this result set, where we already know + /// the hiding declaration (if any). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + /// + /// \param Hiding the declaration that hides the result. + /// + /// \param InBaseClass whether the result was found in a base + /// class of the searched context. + void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, + bool InBaseClass); + + /// Add a new non-declaration result to this result set. + void AddResult(Result R); + + /// Enter into a new scope. + void EnterNewScope(); + + /// Exit from the current scope. + void ExitScope(); + + /// Ignore this declaration, if it is seen again. + void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } + + /// Add a visited context. + void addVisitedContext(DeclContext *Ctx) { + CompletionContext.addVisitedContext(Ctx); + } + + /// \name Name lookup predicates + /// + /// These predicates can be passed to the name lookup functions to filter the + /// results of name lookup. All of the predicates have the same type, so that + /// + //@{ + bool IsOrdinaryName(const NamedDecl *ND) const; + bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; + bool IsIntegralConstantValue(const NamedDecl *ND) const; + bool IsOrdinaryNonValueName(const NamedDecl *ND) const; + bool IsNestedNameSpecifier(const NamedDecl *ND) const; + bool IsEnum(const NamedDecl *ND) const; + bool IsClassOrStruct(const NamedDecl *ND) const; + bool IsUnion(const NamedDecl *ND) const; + bool IsNamespace(const NamedDecl *ND) const; + bool IsNamespaceOrAlias(const NamedDecl *ND) const; + bool IsType(const NamedDecl *ND) const; + bool IsMember(const NamedDecl *ND) const; + bool IsObjCIvar(const NamedDecl *ND) const; + bool IsObjCMessageReceiver(const NamedDecl *ND) const; + bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; + bool IsObjCCollection(const NamedDecl *ND) const; + bool IsImpossibleToSatisfy(const NamedDecl *ND) const; + //@} +}; +} // namespace class ResultBuilder::ShadowMapEntry::iterator { llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator; @@ -364,20 +362,18 @@ public: DeclIndexPair Value; public: - pointer(const DeclIndexPair &Value) : Value(Value) { } + pointer(const DeclIndexPair &Value) : Value(Value) {} - const DeclIndexPair *operator->() const { - return &Value; - } + const DeclIndexPair *operator->() const { return &Value; } }; iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {} iterator(const NamedDecl *SingleDecl, unsigned Index) - : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { } + : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {} iterator(const DeclIndexPair *Iterator) - : DeclOrIterator(Iterator), SingleDeclIndex(0) { } + : DeclOrIterator(Iterator), SingleDeclIndex(0) {} iterator &operator++() { if (DeclOrIterator.is<const NamedDecl *>()) { @@ -386,7 +382,7 @@ public: return *this; } - const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>(); + const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>(); ++I; DeclOrIterator = I; return *this; @@ -402,17 +398,15 @@ public: if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>()) return reference(ND, SingleDeclIndex); - return *DeclOrIterator.get<const DeclIndexPair*>(); + return *DeclOrIterator.get<const DeclIndexPair *>(); } - pointer operator->() const { - return pointer(**this); - } + pointer operator->() const { return pointer(**this); } friend bool operator==(const iterator &X, const iterator &Y) { - return X.DeclOrIterator.getOpaqueValue() - == Y.DeclOrIterator.getOpaqueValue() && - X.SingleDeclIndex == Y.SingleDeclIndex; + return X.DeclOrIterator.getOpaqueValue() == + Y.DeclOrIterator.getOpaqueValue() && + X.SingleDeclIndex == Y.SingleDeclIndex; } friend bool operator!=(const iterator &X, const iterator &Y) { @@ -453,8 +447,7 @@ ResultBuilder::ShadowMapEntry::end() const { /// \returns a nested name specifier that refers into the target context, or /// NULL if no qualification is needed. static NestedNameSpecifier * -getRequiredQualification(ASTContext &Context, - const DeclContext *CurContext, +getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, const DeclContext *TargetContext) { SmallVector<const DeclContext *, 4> TargetParents; @@ -472,16 +465,14 @@ getRequiredQualification(ASTContext &Context, while (!TargetParents.empty()) { const DeclContext *Parent = TargetParents.pop_back_val(); - if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) { + if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) { if (!Namespace->getIdentifier()) continue; Result = NestedNameSpecifier::Create(Context, Result, Namespace); - } - else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent)) - Result = NestedNameSpecifier::Create(Context, Result, - false, - Context.getTypeDeclType(TD).getTypePtr()); + } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) + Result = NestedNameSpecifier::Create( + Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); } return Result; } @@ -494,8 +485,8 @@ static bool isReservedName(const IdentifierInfo *Id, return false; const char *Name = Id->getNameStart(); return Name[0] == '_' && - (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' && - !doubleUnderscoreOnly)); + (Name[1] == '_' || + (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly)); } // Some declarations have reserved names that we don't want to ever show. @@ -514,9 +505,9 @@ static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) { // This allows for system headers providing private symbols with a single // underscore. if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) && - SemaRef.SourceMgr.isInSystemHeader( - SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))) - return true; + SemaRef.SourceMgr.isInSystemHeader( + SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))) + return true; return false; } @@ -550,10 +541,8 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, return false; if (Filter == &ResultBuilder::IsNestedNameSpecifier || - (isa<NamespaceDecl>(ND) && - Filter != &ResultBuilder::IsNamespace && - Filter != &ResultBuilder::IsNamespaceOrAlias && - Filter != nullptr)) + (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace && + Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr)) AsNestedNameSpecifier = true; // Filter out any unwanted results. @@ -597,8 +586,7 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, R.QualifierIsInformative = false; if (!R.Qualifier) - R.Qualifier = getRequiredQualification(SemaRef.Context, - CurContext, + R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext, R.Declaration->getDeclContext()); return false; } @@ -609,23 +597,23 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { switch (T->getTypeClass()) { case Type::Builtin: switch (cast<BuiltinType>(T)->getKind()) { - case BuiltinType::Void: - return STC_Void; + case BuiltinType::Void: + return STC_Void; - case BuiltinType::NullPtr: - return STC_Pointer; + case BuiltinType::NullPtr: + return STC_Pointer; - case BuiltinType::Overload: - case BuiltinType::Dependent: - return STC_Other; + case BuiltinType::Overload: + case BuiltinType::Dependent: + return STC_Other; - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - return STC_ObjectiveC; + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return STC_ObjectiveC; - default: - return STC_Arithmetic; + default: + return STC_Arithmetic; } case Type::Complex: @@ -677,21 +665,21 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { ND = ND->getUnderlyingDecl(); - if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + if (const auto *Type = dyn_cast<TypeDecl>(ND)) return C.getTypeDeclType(Type); - if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) + if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) return C.getObjCInterfaceType(Iface); QualType T; if (const FunctionDecl *Function = ND->getAsFunction()) T = Function->getCallResultType(); - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) T = Method->getSendResultType(); - else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); - else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) T = Property->getType(); - else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) + else if (const auto *Value = dyn_cast<ValueDecl>(ND)) T = Value->getType(); else return QualType(); @@ -700,12 +688,12 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { // get down to the likely type of an expression when the entity is // used. do { - if (const ReferenceType *Ref = T->getAs<ReferenceType>()) { + if (const auto *Ref = T->getAs<ReferenceType>()) { T = Ref->getPointeeType(); continue; } - if (const PointerType *Pointer = T->getAs<PointerType>()) { + if (const auto *Pointer = T->getAs<PointerType>()) { if (Pointer->getPointeeType()->isFunctionType()) { T = Pointer->getPointeeType(); continue; @@ -714,12 +702,12 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { break; } - if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) { + if (const auto *Block = T->getAs<BlockPointerType>()) { T = Block->getPointeeType(); continue; } - if (const FunctionType *Function = T->getAs<FunctionType>()) { + if (const auto *Function = T->getAs<FunctionType>()) { T = Function->getReturnType(); continue; } @@ -738,8 +726,7 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { const DeclContext *LexicalDC = ND->getLexicalDeclContext(); if (LexicalDC->isFunctionOrMethod()) { // _cmd is relatively rare - if (const ImplicitParamDecl *ImplicitParam = - dyn_cast<ImplicitParamDecl>(ND)) + if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND)) if (ImplicitParam->getIdentifier() && ImplicitParam->getIdentifier()->isStr("_cmd")) return CCP_ObjC_cmd; @@ -770,10 +757,10 @@ unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { // likely that the user will want to write a type as other declarations. if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) && !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement || - CompletionContext.getKind() - == CodeCompletionContext::CCC_ObjCMessageReceiver || - CompletionContext.getKind() - == CodeCompletionContext::CCC_ParenthesizedExpression)) + CompletionContext.getKind() == + CodeCompletionContext::CCC_ObjCMessageReceiver || + CompletionContext.getKind() == + CodeCompletionContext::CCC_ParenthesizedExpression)) return CCP_Type; return CCP_Declaration; @@ -783,7 +770,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { // If this is an Objective-C method declaration whose selector matches our // preferred selector, give it a priority boost. if (!PreferredSelector.isNull()) - if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) + if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) if (PreferredSelector == Method->getSelector()) R.Priority += CCD_SelectorMatch; @@ -797,20 +784,28 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) R.Priority /= CCF_ExactTypeMatch; // Check for nearly-matching types, based on classification of each. - else if ((getSimplifiedTypeClass(PreferredType) - == getSimplifiedTypeClass(TC)) && + else if ((getSimplifiedTypeClass(PreferredType) == + getSimplifiedTypeClass(TC)) && !(PreferredType->isEnumeralType() && TC->isEnumeralType())) R.Priority /= CCF_SimilarTypeMatch; } } } +DeclContext::lookup_result getConstructors(ASTContext &Context, + const CXXRecordDecl *Record) { + QualType RecordTy = Context.getTypeDeclType(Record); + DeclarationName ConstructorName = + Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(RecordTy)); + return Record->lookup(ConstructorName); +} + void ResultBuilder::MaybeAddConstructorResults(Result R) { if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || !CompletionContext.wantConstructorResults()) return; - ASTContext &Context = SemaRef.Context; const NamedDecl *D = R.Declaration; const CXXRecordDecl *Record = nullptr; if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) @@ -828,16 +823,8 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) { if (!Record) return; - - QualType RecordTy = Context.getTypeDeclType(Record); - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(RecordTy)); - DeclContext::lookup_result Ctors = Record->lookup(ConstructorName); - for (DeclContext::lookup_iterator I = Ctors.begin(), - E = Ctors.end(); - I != E; ++I) { - R.Declaration = *I; + for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) { + R.Declaration = Ctor; R.CursorKind = getCursorKindForDecl(R.Declaration); Results.push_back(R); } @@ -919,8 +906,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { continue; // Protocols are in distinct namespaces from everything else. - if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) - || (IDNS & Decl::IDNS_ObjCProtocol)) && + if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) || + (IDNS & Decl::IDNS_ObjCProtocol)) && I->first->getIdentifierNamespace() != IDNS) continue; @@ -942,18 +929,19 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { R.StartsNestedNameSpecifier = true; R.Priority = CCP_NestedNameSpecifier; } else - AdjustResultPriorityForDecl(R); + AdjustResultPriorityForDecl(R); // If this result is supposed to have an informative qualifier, add one. if (R.QualifierIsInformative && !R.Qualifier && !R.StartsNestedNameSpecifier) { const DeclContext *Ctx = R.Declaration->getDeclContext(); if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, - Namespace); + R.Qualifier = + NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, - false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + R.Qualifier = NestedNameSpecifier::Create( + SemaRef.Context, nullptr, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else R.QualifierIsInformative = false; } @@ -967,6 +955,11 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { MaybeAddConstructorResults(R); } +static void setInBaseClass(ResultBuilder::Result &R) { + R.Priority += CCD_InBaseClass; + R.InBaseClass = true; +} + void ResultBuilder::AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, bool InBaseClass = false) { if (R.Kind != Result::RK_Declaration) { @@ -976,7 +969,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, } // Look through using declarations. - if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { + if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { CodeCompletionResult Result(Using->getTargetDecl(), getBasePriority(Using->getTargetDecl()), R.Qualifier); @@ -1015,27 +1008,27 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (R.QualifierIsInformative && !R.Qualifier && !R.StartsNestedNameSpecifier) { const DeclContext *Ctx = R.Declaration->getDeclContext(); - if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, - Namespace); - else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false, - SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx)) + R.Qualifier = + NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); + else if (const auto *Tag = dyn_cast<TagDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create( + SemaRef.Context, nullptr, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else R.QualifierIsInformative = false; } // Adjust the priority if this result comes from a base class. if (InBaseClass) - R.Priority += CCD_InBaseClass; + setInBaseClass(R); AdjustResultPriorityForDecl(R); if (HasObjectTypeQualifiers) - if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) + if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) if (Method->isInstance()) { - Qualifiers MethodQuals - = Qualifiers::fromCVRMask(Method->getTypeQualifiers()); + Qualifiers MethodQuals = Method->getTypeQualifiers(); if (ObjectTypeQualifiers == MethodQuals) R.Priority += CCD_ObjectQualifierMatch; else if (ObjectTypeQualifiers - MethodQuals) { @@ -1054,7 +1047,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, void ResultBuilder::AddResult(Result R) { assert(R.Kind != Result::RK_Declaration && - "Declaration results need more context"); + "Declaration results need more context"); Results.push_back(R); } @@ -1064,9 +1057,8 @@ void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); } /// Exit from the current scope. void ResultBuilder::ExitScope() { for (ShadowMap::iterator E = ShadowMaps.back().begin(), - EEnd = ShadowMaps.back().end(); - E != EEnd; - ++E) + EEnd = ShadowMaps.back().end(); + E != EEnd; ++E) E->second.Destroy(); ShadowMaps.pop_back(); @@ -1082,7 +1074,7 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; - else if (SemaRef.getLangOpts().ObjC1) { + else if (SemaRef.getLangOpts().ObjC) { if (isa<ObjCIvarDecl>(ND)) return true; } @@ -1107,7 +1099,7 @@ bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; - else if (SemaRef.getLangOpts().ObjC1) { + else if (SemaRef.getLangOpts().ObjC) { if (isa<ObjCIvarDecl>(ND)) return true; } @@ -1119,7 +1111,7 @@ bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { if (!IsOrdinaryNonTypeName(ND)) return 0; - if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) + if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) if (VD->getType()->isIntegralOrEnumerationType()) return true; @@ -1135,16 +1127,15 @@ bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { if (SemaRef.getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; - return (ND->getIdentifierNamespace() & IDNS) && - !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) && - !isa<ObjCPropertyDecl>(ND); + return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) && + !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND); } /// Determines whether the given declaration is suitable as the /// start of a C++ nested-name-specifier, e.g., a class or namespace. bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); return SemaRef.isAcceptableNestedNameSpecifier(ND); @@ -1158,14 +1149,13 @@ bool ResultBuilder::IsEnum(const NamedDecl *ND) const { /// Determines whether the given declaration is a class or struct. bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); // For purposes of this check, interfaces match too. - if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) - return RD->getTagKind() == TTK_Class || - RD->getTagKind() == TTK_Struct || - RD->getTagKind() == TTK_Interface; + if (const auto *RD = dyn_cast<RecordDecl>(ND)) + return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct || + RD->getTagKind() == TTK_Interface; return false; } @@ -1173,10 +1163,10 @@ bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { /// Determines whether the given declaration is a union. bool ResultBuilder::IsUnion(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); - if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) + if (const auto *RD = dyn_cast<RecordDecl>(ND)) return RD->getTagKind() == TTK_Union; return false; @@ -1250,11 +1240,12 @@ bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { return isObjCReceiverType(SemaRef.Context, T); } -bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const { +bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture( + const NamedDecl *ND) const { if (IsObjCMessageReceiver(ND)) return true; - const VarDecl *Var = dyn_cast<VarDecl>(ND); + const auto *Var = dyn_cast<VarDecl>(ND); if (!Var) return false; @@ -1287,34 +1278,80 @@ bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const { } namespace { - /// Visible declaration consumer that adds a code-completion result - /// for each visible declaration. - class CodeCompletionDeclConsumer : public VisibleDeclConsumer { - ResultBuilder &Results; - DeclContext *CurContext; - std::vector<FixItHint> FixIts; - public: - CodeCompletionDeclConsumer( - ResultBuilder &Results, DeclContext *CurContext, - std::vector<FixItHint> FixIts = std::vector<FixItHint>()) - : Results(Results), CurContext(CurContext), FixIts(std::move(FixIts)) {} +/// Visible declaration consumer that adds a code-completion result +/// for each visible declaration. +class CodeCompletionDeclConsumer : public VisibleDeclConsumer { + ResultBuilder &Results; + DeclContext *InitialLookupCtx; + // NamingClass and BaseType are used for access-checking. See + // Sema::IsSimplyAccessible for details. + CXXRecordDecl *NamingClass; + QualType BaseType; + std::vector<FixItHint> FixIts; - void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, - bool InBaseClass) override { - bool Accessible = true; - if (Ctx) - Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx); - ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, - false, Accessible, FixIts); - Results.AddResult(Result, CurContext, Hiding, InBaseClass); +public: + CodeCompletionDeclConsumer( + ResultBuilder &Results, DeclContext *InitialLookupCtx, + QualType BaseType = QualType(), + std::vector<FixItHint> FixIts = std::vector<FixItHint>()) + : Results(Results), InitialLookupCtx(InitialLookupCtx), + FixIts(std::move(FixIts)) { + NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx); + // If BaseType was not provided explicitly, emulate implicit 'this->'. + if (BaseType.isNull()) { + auto ThisType = Results.getSema().getCurrentThisType(); + if (!ThisType.isNull()) { + assert(ThisType->isPointerType()); + BaseType = ThisType->getPointeeType(); + if (!NamingClass) + NamingClass = BaseType->getAsCXXRecordDecl(); + } } - - void EnteredContext(DeclContext* Ctx) override { - Results.addVisitedContext(Ctx); + this->BaseType = BaseType; + } + + void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, + bool InBaseClass) override { + ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, + false, IsAccessible(ND, Ctx), FixIts); + Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass); + } + + void EnteredContext(DeclContext *Ctx) override { + Results.addVisitedContext(Ctx); + } + +private: + bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) { + // Naming class to use for access check. In most cases it was provided + // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)), + // for unqualified lookup we fallback to the \p Ctx in which we found the + // member. + auto *NamingClass = this->NamingClass; + QualType BaseType = this->BaseType; + if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) { + if (!NamingClass) + NamingClass = Cls; + // When we emulate implicit 'this->' in an unqualified lookup, we might + // end up with an invalid naming class. In that case, we avoid emulating + // 'this->' qualifier to satisfy preconditions of the access checking. + if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() && + !NamingClass->isDerivedFrom(Cls)) { + NamingClass = Cls; + BaseType = QualType(); + } + } else { + // The decl was found outside the C++ class, so only ObjC access checks + // apply. Those do not rely on NamingClass and BaseType, so we clear them + // out. + NamingClass = nullptr; + BaseType = QualType(); } - }; -} + return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType); + } +}; +} // namespace /// Add type specifiers for the current language as keyword results. static void AddTypeSpecifierResults(const LangOptions &LangOpts, @@ -1347,8 +1384,8 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Results.getCodeCompletionTUInfo()); if (LangOpts.CPlusPlus) { // C++-specific - Results.AddResult(Result("bool", CCP_Type + - (LangOpts.ObjC1? CCD_bool_in_ObjC : 0))); + Results.AddResult( + Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0))); Results.AddResult(Result("class", CCP_Type)); Results.AddResult(Result("wchar_t", CCP_Type)); @@ -1464,14 +1501,11 @@ static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); static void AddObjCVisibilityResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt); + ResultBuilder &Results, bool NeedAt); static void AddObjCImplementationResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt); + ResultBuilder &Results, bool NeedAt); static void AddObjCInterfaceResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt); + ResultBuilder &Results, bool NeedAt); static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); static void AddTypedefResult(ResultBuilder &Results) { @@ -1509,7 +1543,7 @@ static bool WantTypesInContext(Sema::ParserCompletionContext CCC, return false; case Sema::PCC_ForInit: - return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99; + return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99; } llvm_unreachable("Invalid ParserCompletionContext!"); @@ -1535,8 +1569,7 @@ static PrintingPolicy getCompletionPrintingPolicy(Sema &S) { /// /// This routine provides a fast path where we provide constant strings for /// common type names. -static const char *GetCompletionTypeString(QualType T, - ASTContext &Context, +static const char *GetCompletionTypeString(QualType T, ASTContext &Context, const PrintingPolicy &Policy, CodeCompletionAllocator &Allocator) { if (!T.getLocalQualifiers()) { @@ -1549,11 +1582,16 @@ static const char *GetCompletionTypeString(QualType T, if (TagDecl *Tag = TagT->getDecl()) if (!Tag->hasNameForLinkage()) { switch (Tag->getTagKind()) { - case TTK_Struct: return "struct <anonymous>"; - case TTK_Interface: return "__interface <anonymous>"; - case TTK_Class: return "class <anonymous>"; - case TTK_Union: return "union <anonymous>"; - case TTK_Enum: return "enum <anonymous>"; + case TTK_Struct: + return "struct <anonymous>"; + case TTK_Interface: + return "__interface <anonymous>"; + case TTK_Class: + return "class <anonymous>"; + case TTK_Union: + return "union <anonymous>"; + case TTK_Enum: + return "enum <anonymous>"; } } } @@ -1573,10 +1611,8 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) { CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); PrintingPolicy Policy = getCompletionPrintingPolicy(S); - Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, - S.Context, - Policy, - Allocator)); + Builder.AddResultTypeChunk( + GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator)); Builder.AddTypedTextChunk("this"); Results.AddResult(CodeCompletionResult(Builder.TakeString())); } @@ -1596,11 +1632,76 @@ static void AddStaticAssertResult(CodeCompletionBuilder &Builder, Results.AddResult(CodeCompletionResult(Builder.TakeString())); } +static void printOverrideString(llvm::raw_ostream &OS, + CodeCompletionString *CCS) { + for (const auto &C : *CCS) { + if (C.Kind == CodeCompletionString::CK_Optional) + printOverrideString(OS, C.Optional); + else + OS << C.Text; + // Add a space after return type. + if (C.Kind == CodeCompletionString::CK_ResultType) + OS << ' '; + } +} + +static void AddOverrideResults(ResultBuilder &Results, + const CodeCompletionContext &CCContext, + CodeCompletionBuilder &Builder) { + Sema &S = Results.getSema(); + const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext); + // If not inside a class/struct/union return empty. + if (!CR) + return; + // First store overrides within current class. + // These are stored by name to make querying fast in the later step. + llvm::StringMap<std::vector<FunctionDecl *>> Overrides; + for (auto *Method : CR->methods()) { + if (!Method->isVirtual() || !Method->getIdentifier()) + continue; + Overrides[Method->getName()].push_back(Method); + } + + for (const auto &Base : CR->bases()) { + const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl(); + if (!BR) + continue; + for (auto *Method : BR->methods()) { + if (!Method->isVirtual() || !Method->getIdentifier()) + continue; + const auto it = Overrides.find(Method->getName()); + bool IsOverriden = false; + if (it != Overrides.end()) { + for (auto *MD : it->second) { + // If the method in current body is not an overload of this virtual + // function, then it overrides this one. + if (!S.IsOverload(MD, Method, false)) { + IsOverriden = true; + break; + } + } + } + if (!IsOverriden) { + // Generates a new CodeCompletionResult by taking this function and + // converting it into an override declaration with only one chunk in the + // final CodeCompletionString as a TypedTextChunk. + std::string OverrideSignature; + llvm::raw_string_ostream OS(OverrideSignature); + CodeCompletionResult CCR(Method, 0); + PrintingPolicy Policy = + getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor()); + auto *CCS = CCR.createCodeCompletionStringForOverride( + S.getPreprocessor(), S.getASTContext(), Builder, + /*IncludeBriefComments=*/false, CCContext, Policy); + Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern)); + } + } + } +} + /// Add language constructs that show up for "ordinary" names. -static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, - Scope *S, - Sema &SemaRef, - ResultBuilder &Results) { +static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, + Sema &SemaRef, ResultBuilder &Results) { CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); @@ -1649,10 +1750,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("declaration"); Results.AddResult(Result(Builder.TakeString())); + } else { + Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); } } - if (SemaRef.getLangOpts().ObjC1) + if (SemaRef.getLangOpts().ObjC) AddObjCTopLevelResults(Results, true); AddTypedefResult(Results); @@ -1704,6 +1807,12 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, if (IsNotInheritanceScope && Results.includeCodePatterns()) Builder.AddChunk(CodeCompletionString::CK_Colon); Results.AddResult(Result(Builder.TakeString())); + + // FIXME: This adds override results only if we are at the first word of + // the declaration/definition. Also call this from other sides to have + // more use-cases. + AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion, + Builder); } } LLVM_FALLTHROUGH; @@ -1717,6 +1826,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddPlaceholderChunk("parameters"); Builder.AddChunk(CodeCompletionString::CK_RightAngle); Results.AddResult(Result(Builder.TakeString())); + } else { + Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); } AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); @@ -1760,7 +1871,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Builder.AddChunk(CodeCompletionString::CK_RightBrace); Results.AddResult(Result(Builder.TakeString())); } - if (SemaRef.getLangOpts().ObjC1) + if (SemaRef.getLangOpts().ObjC) AddObjCStatementResults(Results, true); if (Results.includeCodePatterns()) { @@ -1793,7 +1904,8 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, } // Switch-specific statements. - if (!SemaRef.getCurFunction()->SwitchStack.empty()) { + if (SemaRef.getCurFunction() && + !SemaRef.getCurFunction()->SwitchStack.empty()) { // case expression: Builder.AddTypedTextChunk("case"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -1869,10 +1981,9 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // "return expression ;" or "return ;", depending on whether we // know the function is void or not. bool isVoid = false; - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) + if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) isVoid = Function->getReturnType()->isVoidType(); - else if (ObjCMethodDecl *Method - = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) isVoid = Method->getReturnType()->isVoidType(); else if (SemaRef.getCurBlock() && !SemaRef.getCurBlock()->ReturnType.isNull()) @@ -1900,7 +2011,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); } - LLVM_FALLTHROUGH; + LLVM_FALLTHROUGH; // Fall through (for statement expressions). case Sema::PCC_ForInit: @@ -2087,7 +2198,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, } } - if (SemaRef.getLangOpts().ObjC1) { + if (SemaRef.getLangOpts().ObjC) { // Add "super", if we're in an Objective-C class with a superclass. if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { // The interface can be NULL. @@ -2146,8 +2257,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, /// type chunk. static void AddResultTypeChunk(ASTContext &Context, const PrintingPolicy &Policy, - const NamedDecl *ND, - QualType BaseType, + const NamedDecl *ND, QualType BaseType, CodeCompletionBuilder &Result) { if (!ND) return; @@ -2161,24 +2271,24 @@ static void AddResultTypeChunk(ASTContext &Context, QualType T; if (const FunctionDecl *Function = ND->getAsFunction()) T = Function->getReturnType(); - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { if (!BaseType.isNull()) T = Method->getSendResultType(BaseType); else T = Method->getReturnType(); - } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) { + } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) { T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); T = clang::TypeName::getFullyQualifiedType(T, Context); } else if (isa<UnresolvedUsingValueDecl>(ND)) { /* Do nothing: ignore unresolved using declarations*/ - } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { + } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { if (!BaseType.isNull()) T = Ivar->getUsageType(BaseType); else T = Ivar->getType(); - } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) { + } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) { T = Value->getType(); - } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) { + } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) { if (!BaseType.isNull()) T = Property->getUsageType(BaseType); else @@ -2188,8 +2298,8 @@ static void AddResultTypeChunk(ASTContext &Context, if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) return; - Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy, - Result.getAllocator())); + Result.AddResultTypeChunk( + GetCompletionTypeString(T, Context, Policy, Result.getAllocator())); } static void MaybeAddSentinel(Preprocessor &PP, @@ -2197,7 +2307,7 @@ static void MaybeAddSentinel(Preprocessor &PP, CodeCompletionBuilder &Result) { if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) if (Sentinel->getSentinel() == 0) { - if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil")) + if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil")) Result.AddTextChunk(", nil"); else if (PP.isMacroDefined("NULL")) Result.AddTextChunk(", NULL"); @@ -2295,11 +2405,10 @@ formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl, bool SuppressBlock = false, Optional<ArrayRef<QualType>> ObjCSubsts = None); -static std::string FormatFunctionParameter(const PrintingPolicy &Policy, - const ParmVarDecl *Param, - bool SuppressName = false, - bool SuppressBlock = false, - Optional<ArrayRef<QualType>> ObjCSubsts = None) { +static std::string +FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param, + bool SuppressName = false, bool SuppressBlock = false, + Optional<ArrayRef<QualType>> ObjCSubsts = None) { bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); if (Param->getType()->isDependentType() || !Param->getType()->isBlockPointerType()) { @@ -2315,8 +2424,8 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy, Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts, ObjCSubstitutionContext::Parameter); if (ObjCMethodParam) { - Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), - Type); + Result = + "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type); Result += Type.getAsString(Policy) + ")"; if (Param->getIdentifier() && !SuppressName) Result += Param->getIdentifier()->getName(); @@ -2447,13 +2556,15 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param, bool Invalid = CharSrcRange.isInvalid(); if (Invalid) return ""; - StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid); + StringRef srcText = + Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid); if (Invalid) return ""; if (srcText.empty() || srcText == "=") { // Lexer can't determine the value. - // This happens if the code is incorrect (for example class is forward declared). + // This happens if the code is incorrect (for example class is forward + // declared). return ""; } std::string DefValue(srcText.str()); @@ -2461,7 +2572,8 @@ static std::string GetDefaultValueString(const ParmVarDecl *Param, // this value always has (or always does not have) '=' in front of it if (DefValue.at(0) != '=') { // If we don't have '=' in front of value. - // Lexer returns built-in types values without '=' and user-defined types values with it. + // Lexer returns built-in types values without '=' and user-defined types + // values with it. return " = " + DefValue; } return " " + DefValue; @@ -2501,18 +2613,18 @@ static void AddFunctionParameterChunks(Preprocessor &PP, // Format the placeholder string. std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); if (Param->hasDefaultArg()) - PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts()); + PlaceholderStr += + GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts()); if (Function->isVariadic() && P == N - 1) PlaceholderStr += ", ..."; // Add the placeholder string. Result.AddPlaceholderChunk( - Result.getAllocator().CopyString(PlaceholderStr)); + Result.getAllocator().CopyString(PlaceholderStr)); } - if (const FunctionProtoType *Proto - = Function->getType()->getAs<FunctionProtoType>()) + if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>()) if (Proto->isVariadic()) { if (Proto->getNumParams() == 0) Result.AddPlaceholderChunk("..."); @@ -2522,13 +2634,10 @@ static void AddFunctionParameterChunks(Preprocessor &PP, } /// Add template parameter chunks to the given code completion string. -static void AddTemplateParameterChunks(ASTContext &Context, - const PrintingPolicy &Policy, - const TemplateDecl *Template, - CodeCompletionBuilder &Result, - unsigned MaxParameters = 0, - unsigned Start = 0, - bool InDefaultArg = false) { +static void AddTemplateParameterChunks( + ASTContext &Context, const PrintingPolicy &Policy, + const TemplateDecl *Template, CodeCompletionBuilder &Result, + unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) { bool FirstParameter = true; // Prefer to take the template parameter names from the first declaration of @@ -2539,8 +2648,8 @@ static void AddTemplateParameterChunks(ASTContext &Context, TemplateParameterList::iterator PEnd = Params->end(); if (MaxParameters) PEnd = Params->begin() + MaxParameters; - for (TemplateParameterList::iterator P = Params->begin() + Start; - P != PEnd; ++P) { + for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd; + ++P) { bool HasDefaultArg = false; std::string PlaceholderStr; if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { @@ -2555,8 +2664,8 @@ static void AddTemplateParameterChunks(ASTContext &Context, } HasDefaultArg = TTP->hasDefaultArgument(); - } else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + } else if (NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(*P)) { if (NTTP->getIdentifier()) PlaceholderStr = NTTP->getIdentifier()->getName(); NTTP->getType().getAsStringInternal(PlaceholderStr, Policy); @@ -2598,18 +2707,17 @@ static void AddTemplateParameterChunks(ASTContext &Context, // Add the placeholder string. Result.AddPlaceholderChunk( - Result.getAllocator().CopyString(PlaceholderStr)); + Result.getAllocator().CopyString(PlaceholderStr)); } } /// Add a qualifier to the given code-completion string, if the /// provided nested-name-specifier is non-NULL. -static void -AddQualifierToCompletionString(CodeCompletionBuilder &Result, - NestedNameSpecifier *Qualifier, - bool QualifierIsInformative, - ASTContext &Context, - const PrintingPolicy &Policy) { +static void AddQualifierToCompletionString(CodeCompletionBuilder &Result, + NestedNameSpecifier *Qualifier, + bool QualifierIsInformative, + ASTContext &Context, + const PrintingPolicy &Policy) { if (!Qualifier) return; @@ -2627,25 +2735,24 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result, static void AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, const FunctionDecl *Function) { - const FunctionProtoType *Proto - = Function->getType()->getAs<FunctionProtoType>(); + const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); if (!Proto || !Proto->getTypeQuals()) return; // FIXME: Add ref-qualifier! // Handle single qualifiers without copying - if (Proto->getTypeQuals() == Qualifiers::Const) { + if (Proto->getTypeQuals().hasOnlyConst()) { Result.AddInformativeChunk(" const"); return; } - if (Proto->getTypeQuals() == Qualifiers::Volatile) { + if (Proto->getTypeQuals().hasOnlyVolatile()) { Result.AddInformativeChunk(" volatile"); return; } - if (Proto->getTypeQuals() == Qualifiers::Restrict) { + if (Proto->getTypeQuals().hasOnlyRestrict()) { Result.AddInformativeChunk(" restrict"); return; } @@ -2670,37 +2777,51 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, return; switch (Name.getNameKind()) { - case DeclarationName::CXXOperatorName: { - const char *OperatorName = nullptr; - switch (Name.getCXXOverloadedOperator()) { - case OO_None: - case OO_Conditional: - case NUM_OVERLOADED_OPERATORS: - OperatorName = "operator"; - break; + case DeclarationName::CXXOperatorName: { + const char *OperatorName = nullptr; + switch (Name.getCXXOverloadedOperator()) { + case OO_None: + case OO_Conditional: + case NUM_OVERLOADED_OPERATORS: + OperatorName = "operator"; + break; -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - case OO_##Name: OperatorName = "operator" Spelling; break; -#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + case OO_##Name: \ + OperatorName = "operator" Spelling; \ + break; +#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly) #include "clang/Basic/OperatorKinds.def" - case OO_New: OperatorName = "operator new"; break; - case OO_Delete: OperatorName = "operator delete"; break; - case OO_Array_New: OperatorName = "operator new[]"; break; - case OO_Array_Delete: OperatorName = "operator delete[]"; break; - case OO_Call: OperatorName = "operator()"; break; - case OO_Subscript: OperatorName = "operator[]"; break; - } - Result.AddTypedTextChunk(OperatorName); + case OO_New: + OperatorName = "operator new"; + break; + case OO_Delete: + OperatorName = "operator delete"; + break; + case OO_Array_New: + OperatorName = "operator new[]"; + break; + case OO_Array_Delete: + OperatorName = "operator delete[]"; + break; + case OO_Call: + OperatorName = "operator()"; + break; + case OO_Subscript: + OperatorName = "operator[]"; break; } + Result.AddTypedTextChunk(OperatorName); + break; + } case DeclarationName::Identifier: case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXLiteralOperatorName: Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); break; case DeclarationName::CXXDeductionGuideName: @@ -2713,19 +2834,18 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, case DeclarationName::CXXConstructorName: { CXXRecordDecl *Record = nullptr; QualType Ty = Name.getCXXNameType(); - if (const RecordType *RecordTy = Ty->getAs<RecordType>()) + if (const auto *RecordTy = Ty->getAs<RecordType>()) Record = cast<CXXRecordDecl>(RecordTy->getDecl()); - else if (const InjectedClassNameType *InjectedTy - = Ty->getAs<InjectedClassNameType>()) + else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>()) Record = InjectedTy->getDecl(); else { Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); break; } Result.AddTypedTextChunk( - Result.getAllocator().CopyString(Record->getNameAsString())); + Result.getAllocator().CopyString(Record->getNameAsString())); if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { Result.AddChunk(CodeCompletionString::CK_LeftAngle); AddTemplateParameterChunks(Context, Policy, Template, Result); @@ -2736,11 +2856,10 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, } } -CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S, - const CodeCompletionContext &CCContext, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - bool IncludeBriefComments) { +CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( + Sema &S, const CodeCompletionContext &CCContext, + CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments) { return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator, CCTUInfo, IncludeBriefComments); } @@ -2797,13 +2916,10 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro( /// \returns Either a new, heap-allocated code completion string describing /// how to use this result, or NULL to indicate that the string or name of the /// result is all that is needed. -CodeCompletionString * -CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, - Preprocessor &PP, - const CodeCompletionContext &CCContext, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - bool IncludeBriefComments) { +CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( + ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext, + CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments) { if (Kind == RK_Macro) return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo); @@ -2832,6 +2948,30 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } assert(Kind == RK_Declaration && "Missed a result kind?"); + return createCodeCompletionStringForDecl( + PP, Ctx, Result, IncludeBriefComments, CCContext, Policy); +} + +CodeCompletionString * +CodeCompletionResult::createCodeCompletionStringForOverride( + Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, + bool IncludeBriefComments, const CodeCompletionContext &CCContext, + PrintingPolicy &Policy) { + std::string OverrideSignature; + llvm::raw_string_ostream OS(OverrideSignature); + auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result, + /*IncludeBriefComments=*/false, + CCContext, Policy); + printOverrideString(OS, CCS); + OS << " override"; + Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str())); + return Result.TakeString(); +} + +CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( + Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, + bool IncludeBriefComments, const CodeCompletionContext &CCContext, + PrintingPolicy &Policy) { const NamedDecl *ND = Declaration; Result.addParentContext(ND->getDeclContext()); @@ -2844,7 +2984,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (StartsNestedNameSpecifier) { Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); Result.AddTextChunk("::"); return Result.TakeString(); } @@ -2854,7 +2994,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result); - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { + if (const auto *Function = dyn_cast<FunctionDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); @@ -2865,7 +3005,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } - if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { + if (const FunctionTemplateDecl *FunTmpl = + dyn_cast<FunctionTemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); @@ -2884,16 +3025,16 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, // FIXME: We need to abstract template parameters better! bool HasDefaultArg = false; NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( - LastDeducibleArgument - 1); + LastDeducibleArgument - 1); if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) HasDefaultArg = TTP->hasDefaultArgument(); - else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Param)) + else if (NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(Param)) HasDefaultArg = NTTP->hasDefaultArgument(); else { assert(isa<TemplateTemplateParmDecl>(Param)); - HasDefaultArg - = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); + HasDefaultArg = + cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); } if (!HasDefaultArg) @@ -2919,22 +3060,21 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } - if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { + if (const auto *Template = dyn_cast<TemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); Result.AddTypedTextChunk( - Result.getAllocator().CopyString(Template->getNameAsString())); + Result.getAllocator().CopyString(Template->getNameAsString())); Result.AddChunk(CodeCompletionString::CK_LeftAngle); AddTemplateParameterChunks(Ctx, Policy, Template, Result); Result.AddChunk(CodeCompletionString::CK_RightAngle); return Result.TakeString(); } - - if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { + if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { Selector Sel = Method->getSelector(); if (Sel.isUnarySelector()) { - Result.AddTypedTextChunk(Result.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Sel.getNameForSlot(0))); return Result.TakeString(); } @@ -2952,7 +3092,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } unsigned Idx = 0; for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), - PEnd = Method->param_end(); + PEnd = Method->param_end(); P != PEnd; (void)++P, ++Idx) { if (Idx > 0) { std::string Keyword; @@ -2979,12 +3119,11 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (ParamType->isBlockPointerType() && !DeclaringEntity) Arg = FormatFunctionParameter(Policy, *P, true, - /*SuppressBlock=*/false, - ObjCSubsts); + /*SuppressBlock=*/false, ObjCSubsts); else { if (ObjCSubsts) - ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts, - ObjCSubstitutionContext::Parameter); + ParamType = ParamType.substObjCTypeArgs( + Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter); Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(), ParamType); Arg += ParamType.getAsString(Policy) + ")"; @@ -3025,7 +3164,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Ctx, Policy); Result.AddTypedTextChunk( - Result.getAllocator().CopyString(ND->getNameAsString())); + Result.getAllocator().CopyString(ND->getNameAsString())); return Result.TakeString(); } @@ -3037,7 +3176,7 @@ const RawComment *clang::getCompletionComment(const ASTContext &Ctx, return RC; // Try to find comment from a property for ObjC methods. - const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND); + const auto *M = dyn_cast<ObjCMethodDecl>(ND); if (!M) return nullptr; const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); @@ -3049,7 +3188,7 @@ const RawComment *clang::getCompletionComment(const ASTContext &Ctx, const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx, const NamedDecl *ND) { - const ObjCMethodDecl *M = dyn_cast_or_null<ObjCMethodDecl>(ND); + const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND); if (!M || !M->isPropertyAccessor()) return nullptr; @@ -3072,8 +3211,7 @@ const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx, const RawComment *clang::getParameterComment( const ASTContext &Ctx, - const CodeCompleteConsumer::OverloadCandidate &Result, - unsigned ArgIndex) { + const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) { auto FDecl = Result.getFunction(); if (!FDecl) return nullptr; @@ -3089,12 +3227,11 @@ static void AddOverloadParameterChunks(ASTContext &Context, const FunctionDecl *Function, const FunctionProtoType *Prototype, CodeCompletionBuilder &Result, - unsigned CurrentArg, - unsigned Start = 0, + unsigned CurrentArg, unsigned Start = 0, bool InOptional = false) { bool FirstParameter = true; - unsigned NumParams = Function ? Function->getNumParams() - : Prototype->getNumParams(); + unsigned NumParams = + Function ? Function->getNumParams() : Prototype->getNumParams(); for (unsigned P = Start; P != NumParams; ++P) { if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) { @@ -3124,14 +3261,15 @@ static void AddOverloadParameterChunks(ASTContext &Context, const ParmVarDecl *Param = Function->getParamDecl(P); Placeholder = FormatFunctionParameter(Policy, Param); if (Param->hasDefaultArg()) - Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts()); + Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), + Context.getLangOpts()); } else { Placeholder = Prototype->getParamType(P).getAsString(Policy); } if (P == CurrentArg) Result.AddCurrentParameterChunk( - Result.getAllocator().CopyString(Placeholder)); + Result.getAllocator().CopyString(Placeholder)); else Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder)); } @@ -3153,23 +3291,22 @@ static void AddOverloadParameterChunks(ASTContext &Context, CodeCompletionString * CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( - unsigned CurrentArg, Sema &S, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - bool IncludeBriefComments) const { + unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const { PrintingPolicy Policy = getCompletionPrintingPolicy(S); // FIXME: Set priority, availability appropriately. - CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available); + CodeCompletionBuilder Result(Allocator, CCTUInfo, 1, + CXAvailability_Available); FunctionDecl *FDecl = getFunction(); - const FunctionProtoType *Proto - = dyn_cast<FunctionProtoType>(getFunctionType()); + const FunctionProtoType *Proto = + dyn_cast<FunctionProtoType>(getFunctionType()); if (!FDecl && !Proto) { // Function without a prototype. Just give the return type and a // highlighted ellipsis. const FunctionType *FT = getFunctionType(); Result.AddResultTypeChunk(Result.getAllocator().CopyString( - FT->getReturnType().getAsString(Policy))); + FT->getReturnType().getAsString(Policy))); Result.AddChunk(CodeCompletionString::CK_LeftParen); Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); Result.AddChunk(CodeCompletionString::CK_RightParen); @@ -3183,10 +3320,9 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( } AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result); Result.AddTextChunk( - Result.getAllocator().CopyString(FDecl->getNameAsString())); + Result.getAllocator().CopyString(FDecl->getNameAsString())); } else { - Result.AddResultTypeChunk( - Result.getAllocator().CopyString( + Result.AddResultTypeChunk(Result.getAllocator().CopyString( Proto->getReturnType().getAsString(Policy))); } @@ -3216,8 +3352,7 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName, Priority = CCP_Constant; // Treat "bool" as a type. else if (MacroName.equals("bool")) - Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0); - + Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0); return Priority; } @@ -3227,105 +3362,142 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) { return CXCursor_UnexposedDecl; switch (D->getKind()) { - case Decl::Enum: return CXCursor_EnumDecl; - case Decl::EnumConstant: return CXCursor_EnumConstantDecl; - case Decl::Field: return CXCursor_FieldDecl; - case Decl::Function: - return CXCursor_FunctionDecl; - case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; - case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; - case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; - - case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; - case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; - case Decl::ObjCMethod: - return cast<ObjCMethodDecl>(D)->isInstanceMethod() - ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl; - case Decl::CXXMethod: return CXCursor_CXXMethod; - case Decl::CXXConstructor: return CXCursor_Constructor; - case Decl::CXXDestructor: return CXCursor_Destructor; - case Decl::CXXConversion: return CXCursor_ConversionFunction; - case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl; - case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; - case Decl::ParmVar: return CXCursor_ParmDecl; - case Decl::Typedef: return CXCursor_TypedefDecl; - case Decl::TypeAlias: return CXCursor_TypeAliasDecl; - case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl; - case Decl::Var: return CXCursor_VarDecl; - case Decl::Namespace: return CXCursor_Namespace; - case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; - case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter; - case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter; - case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter; - case Decl::FunctionTemplate: return CXCursor_FunctionTemplate; - case Decl::ClassTemplate: return CXCursor_ClassTemplate; - case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier; - case Decl::ClassTemplatePartialSpecialization: - return CXCursor_ClassTemplatePartialSpecialization; - case Decl::UsingDirective: return CXCursor_UsingDirective; - case Decl::StaticAssert: return CXCursor_StaticAssert; - case Decl::Friend: return CXCursor_FriendDecl; - case Decl::TranslationUnit: return CXCursor_TranslationUnit; - - case Decl::Using: - case Decl::UnresolvedUsingValue: - case Decl::UnresolvedUsingTypename: - return CXCursor_UsingDeclaration; - - case Decl::ObjCPropertyImpl: - switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { - case ObjCPropertyImplDecl::Dynamic: - return CXCursor_ObjCDynamicDecl; - - case ObjCPropertyImplDecl::Synthesize: - return CXCursor_ObjCSynthesizeDecl; - } + case Decl::Enum: + return CXCursor_EnumDecl; + case Decl::EnumConstant: + return CXCursor_EnumConstantDecl; + case Decl::Field: + return CXCursor_FieldDecl; + case Decl::Function: + return CXCursor_FunctionDecl; + case Decl::ObjCCategory: + return CXCursor_ObjCCategoryDecl; + case Decl::ObjCCategoryImpl: + return CXCursor_ObjCCategoryImplDecl; + case Decl::ObjCImplementation: + return CXCursor_ObjCImplementationDecl; + + case Decl::ObjCInterface: + return CXCursor_ObjCInterfaceDecl; + case Decl::ObjCIvar: + return CXCursor_ObjCIvarDecl; + case Decl::ObjCMethod: + return cast<ObjCMethodDecl>(D)->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl; + case Decl::CXXMethod: + return CXCursor_CXXMethod; + case Decl::CXXConstructor: + return CXCursor_Constructor; + case Decl::CXXDestructor: + return CXCursor_Destructor; + case Decl::CXXConversion: + return CXCursor_ConversionFunction; + case Decl::ObjCProperty: + return CXCursor_ObjCPropertyDecl; + case Decl::ObjCProtocol: + return CXCursor_ObjCProtocolDecl; + case Decl::ParmVar: + return CXCursor_ParmDecl; + case Decl::Typedef: + return CXCursor_TypedefDecl; + case Decl::TypeAlias: + return CXCursor_TypeAliasDecl; + case Decl::TypeAliasTemplate: + return CXCursor_TypeAliasTemplateDecl; + case Decl::Var: + return CXCursor_VarDecl; + case Decl::Namespace: + return CXCursor_Namespace; + case Decl::NamespaceAlias: + return CXCursor_NamespaceAlias; + case Decl::TemplateTypeParm: + return CXCursor_TemplateTypeParameter; + case Decl::NonTypeTemplateParm: + return CXCursor_NonTypeTemplateParameter; + case Decl::TemplateTemplateParm: + return CXCursor_TemplateTemplateParameter; + case Decl::FunctionTemplate: + return CXCursor_FunctionTemplate; + case Decl::ClassTemplate: + return CXCursor_ClassTemplate; + case Decl::AccessSpec: + return CXCursor_CXXAccessSpecifier; + case Decl::ClassTemplatePartialSpecialization: + return CXCursor_ClassTemplatePartialSpecialization; + case Decl::UsingDirective: + return CXCursor_UsingDirective; + case Decl::StaticAssert: + return CXCursor_StaticAssert; + case Decl::Friend: + return CXCursor_FriendDecl; + case Decl::TranslationUnit: + return CXCursor_TranslationUnit; + + case Decl::Using: + case Decl::UnresolvedUsingValue: + case Decl::UnresolvedUsingTypename: + return CXCursor_UsingDeclaration; + + case Decl::ObjCPropertyImpl: + switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { + case ObjCPropertyImplDecl::Dynamic: + return CXCursor_ObjCDynamicDecl; + + case ObjCPropertyImplDecl::Synthesize: + return CXCursor_ObjCSynthesizeDecl; + } + llvm_unreachable("Unexpected Kind!"); + + case Decl::Import: + return CXCursor_ModuleImportDecl; + + case Decl::ObjCTypeParam: + return CXCursor_TemplateTypeParameter; - case Decl::Import: - return CXCursor_ModuleImportDecl; - - case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter; - - default: - if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { - switch (TD->getTagKind()) { - case TTK_Interface: // fall through - case TTK_Struct: return CXCursor_StructDecl; - case TTK_Class: return CXCursor_ClassDecl; - case TTK_Union: return CXCursor_UnionDecl; - case TTK_Enum: return CXCursor_EnumDecl; - } + default: + if (const auto *TD = dyn_cast<TagDecl>(D)) { + switch (TD->getTagKind()) { + case TTK_Interface: // fall through + case TTK_Struct: + return CXCursor_StructDecl; + case TTK_Class: + return CXCursor_ClassDecl; + case TTK_Union: + return CXCursor_UnionDecl; + case TTK_Enum: + return CXCursor_EnumDecl; } + } } return CXCursor_UnexposedDecl; } static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, - bool IncludeUndefined, + bool LoadExternal, bool IncludeUndefined, bool TargetTypeIsPointer = false) { typedef CodeCompletionResult Result; Results.EnterNewScope(); - for (Preprocessor::macro_iterator M = PP.macro_begin(), - MEnd = PP.macro_end(); + for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal), + MEnd = PP.macro_end(LoadExternal); M != MEnd; ++M) { auto MD = PP.getMacroDefinition(M->first); if (IncludeUndefined || MD) { - if (MacroInfo *MI = MD.getMacroInfo()) - if (MI->isUsedForHeaderGuard()) - continue; + MacroInfo *MI = MD.getMacroInfo(); + if (MI && MI->isUsedForHeaderGuard()) + continue; - Results.AddResult(Result(M->first, - getMacroUsagePriority(M->first->getName(), - PP.getLangOpts(), - TargetTypeIsPointer))); + Results.AddResult( + Result(M->first, MI, + getMacroUsagePriority(M->first->getName(), PP.getLangOpts(), + TargetTypeIsPointer))); } } Results.ExitScope(); - } static void AddPrettyFunctionResults(const LangOptions &LangOpts, @@ -3350,8 +3522,8 @@ static void HandleCodeCompleteResults(Sema *S, CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); } -static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, - Sema::ParserCompletionContext PCC) { +static CodeCompletionContext +mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) { switch (PCC) { case Sema::PCC_Namespace: return CodeCompletionContext::CCC_TopLevel; @@ -3381,14 +3553,16 @@ static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, case Sema::PCC_ForInit: if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || - S.getLangOpts().ObjC1) + S.getLangOpts().ObjC) return CodeCompletionContext::CCC_ParenthesizedExpression; else return CodeCompletionContext::CCC_Expression; case Sema::PCC_Expression: - case Sema::PCC_Condition: return CodeCompletionContext::CCC_Expression; + case Sema::PCC_Condition: + return CodeCompletionContext(CodeCompletionContext::CCC_Expression, + S.getASTContext().BoolTy); case Sema::PCC_Statement: return CodeCompletionContext::CCC_Statement; @@ -3421,7 +3595,6 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, while (isa<BlockDecl>(CurContext)) CurContext = CurContext->getParent(); - CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext); if (!Method || !Method->isVirtual()) return; @@ -3441,9 +3614,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, // If we need a nested-name-specifier, add one now. if (!InContext) { - NestedNameSpecifier *NNS - = getRequiredQualification(S.Context, CurContext, - Overridden->getDeclContext()); + NestedNameSpecifier *NNS = getRequiredQualification( + S.Context, CurContext, Overridden->getDeclContext()); if (NNS) { std::string Str; llvm::raw_string_ostream OS(Str); @@ -3453,8 +3625,8 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, } else if (!InContext->Equals(Overridden->getDeclContext())) continue; - Builder.AddTypedTextChunk(Results.getAllocator().CopyString( - Overridden->getNameAsString())); + Builder.AddTypedTextChunk( + Results.getAllocator().CopyString(Overridden->getNameAsString())); Builder.AddChunk(CodeCompletionString::CK_LeftParen); bool FirstParam = true; for (auto P : Method->parameters()) { @@ -3467,11 +3639,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, Results.getAllocator().CopyString(P->getIdentifier()->getName())); } Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - CCP_SuperCompletion, - CXCursor_CXXMethod, - CXAvailability_Available, - Overridden)); + Results.AddResult(CodeCompletionResult( + Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod, + CXAvailability_Available, Overridden)); Results.Ignore(Overridden); } } @@ -3493,39 +3663,35 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, PP.getHeaderSearchInfo().collectAllModules(Modules); for (unsigned I = 0, N = Modules.size(); I != N; ++I) { Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString(Modules[I]->Name)); - Results.AddResult(Result(Builder.TakeString(), - CCP_Declaration, - CXCursor_ModuleImportDecl, - Modules[I]->isAvailable() - ? CXAvailability_Available - : CXAvailability_NotAvailable)); + Builder.getAllocator().CopyString(Modules[I]->Name)); + Results.AddResult(Result( + Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, + Modules[I]->isAvailable() ? CXAvailability_Available + : CXAvailability_NotAvailable)); } } else if (getLangOpts().Modules) { // Load the named module. - Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, - Module::AllVisible, - /*IsInclusionDirective=*/false); + Module *Mod = + PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, + /*IsInclusionDirective=*/false); // Enumerate submodules. if (Mod) { for (Module::submodule_iterator Sub = Mod->submodule_begin(), - SubEnd = Mod->submodule_end(); + SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) { Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString((*Sub)->Name)); - Results.AddResult(Result(Builder.TakeString(), - CCP_Declaration, - CXCursor_ModuleImportDecl, - (*Sub)->isAvailable() - ? CXAvailability_Available - : CXAvailability_NotAvailable)); + Builder.getAllocator().CopyString((*Sub)->Name)); + Results.AddResult(Result( + Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, + (*Sub)->isAvailable() ? CXAvailability_Available + : CXAvailability_NotAvailable)); } } } Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); } void Sema::CodeCompleteOrdinaryName(Scope *S, @@ -3572,10 +3738,9 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, // If we are in a C++ non-static member function, check the qualifiers on // the member function to filter/prioritize the results list. - if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) - if (CurMethod->isInstance()) - Results.setObjectTypeQualifiers( - Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers())); + auto ThisType = getCurrentThisType(); + if (!ThisType.isNull()) + Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers()); CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, @@ -3609,28 +3774,30 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, } if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); } static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, ArrayRef<IdentifierInfo *> SelIdents, - bool AtArgumentExpression, - bool IsSuper, + bool AtArgumentExpression, bool IsSuper, ResultBuilder &Results); void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, bool AllowNestedNameSpecifiers) { typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - AllowNestedNameSpecifiers - ? CodeCompletionContext::CCC_PotentiallyQualifiedName - : CodeCompletionContext::CCC_Name); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + AllowNestedNameSpecifiers + // FIXME: Try to separate codepath leading here to deduce whether we + // need an existing symbol or a new one. + ? CodeCompletionContext::CCC_SymbolOrNewName + : CodeCompletionContext::CCC_NewName); Results.EnterNewScope(); // Type qualifiers can come after names. @@ -3671,12 +3838,11 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, DS.getTypeSpecType() == DeclSpec::TST_typename && DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && - !DS.isTypeAltiVecVector() && - S && + !DS.isTypeAltiVecVector() && S && (S->getFlags() & Scope::DeclScope) != 0 && (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | - Scope::FunctionPrototypeScope | - Scope::AtCatchScope)) == 0) { + Scope::FunctionPrototypeScope | Scope::AtCatchScope)) == + 0) { ParsedType T = DS.getRepAsType(); if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) AddClassMessageCompletions(*this, S, T, None, false, false, Results); @@ -3685,15 +3851,14 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, // Note that we intentionally suppress macro results here, since we do not // encourage using macros to produce the names of entities. - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } struct Sema::CodeCompleteExpressionData { CodeCompleteExpressionData(QualType PreferredType = QualType()) - : PreferredType(PreferredType), IntegralConstantExpression(false), - ObjCCollection(false) { } + : PreferredType(PreferredType), IntegralConstantExpression(false), + ObjCCollection(false) {} QualType PreferredType; bool IntegralConstantExpression; @@ -3737,31 +3902,35 @@ void Sema::CodeCompleteExpression(Scope *S, bool PreferredTypeIsPointer = false; if (!Data.PreferredType.isNull()) - PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() - || Data.PreferredType->isMemberPointerType() - || Data.PreferredType->isBlockPointerType(); + PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() || + Data.PreferredType->isMemberPointerType() || + Data.PreferredType->isBlockPointerType(); - if (S->getFnParent() && - !Data.ObjCCollection && + if (S->getFnParent() && !Data.ObjCCollection && !Data.IntegralConstantExpression) AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false, PreferredTypeIsPointer); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false, + PreferredTypeIsPointer); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } +void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) { + return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType)); +} + void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { if (E.isInvalid()) CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); - else if (getLangOpts().ObjC1) + else if (getLangOpts().ObjC) CodeCompleteObjCInstanceMessage(S, E.get(), None, false); } /// The set of properties that have already been added, referenced by /// property name. -typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet; +typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet; /// Retrieve the container definition, if any? static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) { @@ -3819,11 +3988,13 @@ static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy, Builder.AddChunk(CodeCompletionString::CK_RightParen); } -static void AddObjCProperties( - const CodeCompletionContext &CCContext, ObjCContainerDecl *Container, - bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext, - AddedPropertiesSet &AddedProperties, ResultBuilder &Results, - bool IsBaseExprStatement = false, bool IsClassProperty = false) { +static void +AddObjCProperties(const CodeCompletionContext &CCContext, + ObjCContainerDecl *Container, bool AllowCategories, + bool AllowNullaryMethods, DeclContext *CurContext, + AddedPropertiesSet &AddedProperties, ResultBuilder &Results, + bool IsBaseExprStatement = false, + bool IsClassProperty = false, bool InOriginalClass = true) { typedef CodeCompletionResult Result; // Retrieve the definition. @@ -3838,8 +4009,10 @@ static void AddObjCProperties( // expressions. if (!P->getType().getTypePtr()->isBlockPointerType() || !IsBaseExprStatement) { - Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr), - CurContext); + Result R = Result(P, Results.getBasePriority(P), nullptr); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); return; } @@ -3850,8 +4023,10 @@ static void AddObjCProperties( findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc, BlockProtoLoc); if (!BlockLoc) { - Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr), - CurContext); + Result R = Result(P, Results.getBasePriority(P), nullptr); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); return; } @@ -3862,9 +4037,10 @@ static void AddObjCProperties( AddObjCBlockCall(Container->getASTContext(), getCompletionPrintingPolicy(Results.getSema()), Builder, P, BlockLoc, BlockProtoLoc); - Results.MaybeAddResult( - Result(Builder.TakeString(), P, Results.getBasePriority(P)), - CurContext); + Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P)); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); // Provide additional block setter completion iff the base expression is a // statement and the block property is mutable. @@ -3890,13 +4066,15 @@ static void AddObjCProperties( // otherwise the setter completion should show up before the default // property completion, as we normally want to use the result of the // call. - Results.MaybeAddResult( + Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P) + (BlockLoc.getTypePtr()->getReturnType()->isVoidType() ? CCD_BlockPropertySetter - : -CCD_BlockPropertySetter)), - CurContext); + : -CCD_BlockPropertySetter)); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); } }; @@ -3924,10 +4102,11 @@ static void AddObjCProperties( AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder); Builder.AddTypedTextChunk( Results.getAllocator().CopyString(Name->getName())); - Results.MaybeAddResult( - Result(Builder.TakeString(), M, - CCP_MemberDeclaration + CCD_MethodAsProperty), - CurContext); + Result R = Result(Builder.TakeString(), M, + CCP_MemberDeclaration + CCD_MethodAsProperty); + if (!InOriginalClass) + setInBaseClass(R); + Results.MaybeAddResult(R, CurContext); }; if (IsClassProperty) { @@ -3953,42 +4132,47 @@ static void AddObjCProperties( for (auto *P : Protocol->protocols()) AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); - } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ + IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); + } else if (ObjCInterfaceDecl *IFace = + dyn_cast<ObjCInterfaceDecl>(Container)) { if (AllowCategories) { // Look through categories. for (auto *Cat : IFace->known_categories()) AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); + IsBaseExprStatement, IsClassProperty, + InOriginalClass); } // Look through protocols. for (auto *I : IFace->all_referenced_protocols()) AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); + IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); // Look in the superclass. if (IFace->getSuperClass()) AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, - Results, IsBaseExprStatement, IsClassProperty); - } else if (const ObjCCategoryDecl *Category - = dyn_cast<ObjCCategoryDecl>(Container)) { + Results, IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); + } else if (const auto *Category = + dyn_cast<ObjCCategoryDecl>(Container)) { // Look through protocols. for (auto *P : Category->protocols()) AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results, - IsBaseExprStatement, IsClassProperty); + IsBaseExprStatement, IsClassProperty, + /*InOriginalClass*/ false); } } -static void AddRecordMembersCompletionResults(Sema &SemaRef, - ResultBuilder &Results, Scope *S, - QualType BaseType, - RecordDecl *RD, - Optional<FixItHint> AccessOpFixIt) { +static void +AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results, + Scope *S, QualType BaseType, RecordDecl *RD, + Optional<FixItHint> AccessOpFixIt) { // Indicate that we are performing a member access, and the cv-qualifiers // for the base object type. Results.setObjectTypeQualifiers(BaseType.getQualifiers()); @@ -3997,8 +4181,8 @@ static void AddRecordMembersCompletionResults(Sema &SemaRef, Results.allowNestedNameSpecifiers(); std::vector<FixItHint> FixIts; if (AccessOpFixIt) - FixIts.emplace_back(AccessOpFixIt.getValue()); - CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext, std::move(FixIts)); + FixIts.emplace_back(AccessOpFixIt.getValue()); + CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts)); SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, SemaRef.CodeCompleter->includeGlobals(), /*IncludeDependentBases=*/true, @@ -4039,7 +4223,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, enum CodeCompletionContext::Kind contextKind; if (IsArrow) { - if (const PointerType *Ptr = ConvertedBaseType->getAs<PointerType>()) + if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>()) ConvertedBaseType = Ptr->getPointeeType(); } @@ -4059,7 +4243,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, CodeCompleter->getCodeCompletionTUInfo(), CCContext, &ResultBuilder::IsMember); - auto DoCompletion = [&](Expr *Base, bool IsArrow, Optional<FixItHint> AccessOpFixIt) -> bool { + auto DoCompletion = [&](Expr *Base, bool IsArrow, + Optional<FixItHint> AccessOpFixIt) -> bool { if (!Base) return false; @@ -4113,7 +4298,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals()) AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true, CurContext, AddedProperties, Results, - IsBaseExprStatement); + IsBaseExprStatement, /*IsClassProperty*/ false, + /*InOriginalClass*/ false); } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || (!IsArrow && BaseType->isObjCObjectType())) { // Objective-C instance variable access. @@ -4126,7 +4312,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, // Add all ivars from this class and its superclasses. if (Class) { - CodeCompletionDeclConsumer Consumer(Results, CurContext); + CodeCompletionDeclConsumer Consumer(Results, Class, BaseType); Results.setFilter(&ResultBuilder::IsObjCIvar); LookupVisibleDecls( Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(), @@ -4188,8 +4374,8 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { return; ResultBuilder::LookupFilter Filter = nullptr; - enum CodeCompletionContext::Kind ContextKind - = CodeCompletionContext::CCC_Other; + enum CodeCompletionContext::Kind ContextKind = + CodeCompletionContext::CCC_Other; switch ((DeclSpec::TST)TagSpec) { case DeclSpec::TST_enum: Filter = &ResultBuilder::IsEnum; @@ -4231,7 +4417,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { } HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); } static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results, @@ -4255,8 +4441,7 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { Results.EnterNewScope(); AddTypeQualifierResults(DS, Results, LangOpts); Results.ExitScope(); - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -4291,6 +4476,9 @@ void Sema::CodeCompleteCase(Scope *S) { return; SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer(); + // Condition expression might be invalid, do not continue in this case. + if (!Switch->getCond()) + return; QualType type = Switch->getCond()->IgnoreImplicit()->getType(); if (!type->isEnumeralType()) { CodeCompleteExpressionData Data(type); @@ -4318,9 +4506,9 @@ void Sema::CodeCompleteCase(Scope *S) { continue; Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal)) - if (EnumConstantDecl *Enumerator - = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal)) + if (auto *Enumerator = + dyn_cast<EnumConstantDecl>(DRE->getDecl())) { // We look into the AST of the case statement to determine which // enumerator was named. Alternatively, we could compute the value of // the integral constant expression, then compare it against the @@ -4366,7 +4554,7 @@ void Sema::CodeCompleteCase(Scope *S) { Results.ExitScope(); if (CodeCompleter->includeMacros()) { - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); } HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); @@ -4385,10 +4573,9 @@ static bool anyNullArguments(ArrayRef<Expr *> Args) { typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; -static void mergeCandidatesWithResults(Sema &SemaRef, - SmallVectorImpl<ResultCandidate> &Results, - OverloadCandidateSet &CandidateSet, - SourceLocation Loc) { +static void mergeCandidatesWithResults( + Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results, + OverloadCandidateSet &CandidateSet, SourceLocation Loc) { if (!CandidateSet.empty()) { // Sort the overload candidate set by placing the best overloads first. std::stable_sort( @@ -4399,7 +4586,7 @@ static void mergeCandidatesWithResults(Sema &SemaRef, }); // Add the remaining viable overload candidates as code-completion results. - for (auto &Candidate : CandidateSet) { + for (OverloadCandidate &Candidate : CandidateSet) { if (Candidate.Function && Candidate.Function->isDeleted()) continue; if (Candidate.Viable) @@ -4411,22 +4598,21 @@ static void mergeCandidatesWithResults(Sema &SemaRef, /// Get the type of the Nth parameter from a given set of overload /// candidates. static QualType getParamType(Sema &SemaRef, - ArrayRef<ResultCandidate> Candidates, - unsigned N) { + ArrayRef<ResultCandidate> Candidates, unsigned N) { // Given the overloads 'Candidates' for a function call matching all arguments // up to N, return the type of the Nth parameter if it is the same for all // overload candidates. QualType ParamType; for (auto &Candidate : Candidates) { - if (auto FType = Candidate.getFunctionType()) - if (auto Proto = dyn_cast<FunctionProtoType>(FType)) + if (const auto *FType = Candidate.getFunctionType()) + if (const auto *Proto = dyn_cast<FunctionProtoType>(FType)) if (N < Proto->getNumParams()) { if (ParamType.isNull()) ParamType = Proto->getParamType(N); else if (!SemaRef.Context.hasSameUnqualifiedType( - ParamType.getNonReferenceType(), - Proto->getParamType(N).getNonReferenceType())) + ParamType.getNonReferenceType(), + Proto->getParamType(N).getNonReferenceType())) // Otherwise return a default-constructed QualType. return QualType(); } @@ -4435,41 +4621,28 @@ static QualType getParamType(Sema &SemaRef, return ParamType; } -static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S, - MutableArrayRef<ResultCandidate> Candidates, - unsigned CurrentArg, - bool CompleteExpressionWithCurrentArg = true) { - QualType ParamType; - if (CompleteExpressionWithCurrentArg) - ParamType = getParamType(SemaRef, Candidates, CurrentArg); - - if (ParamType.isNull()) - SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression); - else - SemaRef.CodeCompleteExpression(S, ParamType); - - if (!Candidates.empty()) - SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg, - Candidates.data(), - Candidates.size()); +static QualType +ProduceSignatureHelp(Sema &SemaRef, Scope *S, + MutableArrayRef<ResultCandidate> Candidates, + unsigned CurrentArg, SourceLocation OpenParLoc) { + if (Candidates.empty()) + return QualType(); + SemaRef.CodeCompleter->ProcessOverloadCandidates( + SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc); + return getParamType(SemaRef, Candidates, CurrentArg); } -void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { +QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, + ArrayRef<Expr *> Args, + SourceLocation OpenParLoc) { if (!CodeCompleter) - return; - - // When we're code-completing for a call, we fall back to ordinary - // name code-completion whenever we can't produce specific - // results. We may want to revisit this strategy in the future, - // e.g., by merging the two kinds of results. + return QualType(); // FIXME: Provide support for variadic template functions. - // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || Expr::hasAnyTypeDependentArguments(Args)) { - CodeCompleteOrdinaryName(S, PCC_Expression); - return; + return QualType(); } // Build an overload candidate set based on the functions we find. @@ -4498,13 +4671,12 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true, - FirstArgumentIsBase); + /*PartialOverloading=*/true, FirstArgumentIsBase); } else { FunctionDecl *FD = nullptr; - if (auto MCE = dyn_cast<MemberExpr>(NakedFn)) + if (auto *MCE = dyn_cast<MemberExpr>(NakedFn)) FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl()); - else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn)) + else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn)) FD = dyn_cast<FunctionDecl>(DRE->getDecl()); if (FD) { // We check whether it's a resolved function declaration. if (!getLangOpts().CPlusPlus || @@ -4521,8 +4693,8 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { // call operator, so we check if it does and add them as candidates. // A complete type is needed to lookup for member function call operators. if (isCompleteType(Loc, NakedFn->getType())) { - DeclarationName OpName = Context.DeclarationNames - .getCXXOperatorName(OO_Call); + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Call); LookupResult R(*this, OpName, Loc, LookupOrdinaryName); LookupQualifiedName(R, DC); R.suppressDiagnostics(); @@ -4542,7 +4714,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { if (auto FP = T->getAs<FunctionProtoType>()) { if (!TooManyArguments(FP->getNumParams(), Args.size(), - /*PartialOverloading=*/true) || + /*PartialOverloading=*/true) || FP->isVariadic()) Results.push_back(ResultCandidate(FP)); } else if (auto FT = T->getAs<FunctionType>()) @@ -4550,49 +4722,67 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { Results.push_back(ResultCandidate(FT)); } } - mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); - CodeCompleteOverloadResults(*this, S, Results, Args.size(), - !CandidateSet.empty()); + QualType ParamType = + ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); + return !CandidateSet.empty() ? ParamType : QualType(); } -void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, - ArrayRef<Expr *> Args) { +QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, + SourceLocation Loc, + ArrayRef<Expr *> Args, + SourceLocation OpenParLoc) { if (!CodeCompleter) - return; + return QualType(); // A complete type is needed to lookup for constructors. CXXRecordDecl *RD = isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr; - if (!RD) { - CodeCompleteExpression(S, Type); - return; - } + if (!RD) + return Type; // FIXME: Provide support for member initializers. // FIXME: Provide support for variadic template constructors. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - for (auto C : LookupConstructors(RD)) { - if (auto FD = dyn_cast<FunctionDecl>(C)) { - AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), - Args, CandidateSet, + for (NamedDecl *C : LookupConstructors(RD)) { + if (auto *FD = dyn_cast<FunctionDecl>(C)) { + AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, + CandidateSet, /*SuppressUsedConversions=*/false, /*PartialOverloading=*/true); - } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) { - AddTemplateOverloadCandidate(FTD, - DeclAccessPair::make(FTD, C->getAccess()), - /*ExplicitTemplateArgs=*/nullptr, - Args, CandidateSet, - /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true); + } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) { + AddTemplateOverloadCandidate( + FTD, DeclAccessPair::make(FTD, C->getAccess()), + /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); } } SmallVector<ResultCandidate, 8> Results; mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); - CodeCompleteOverloadResults(*this, S, Results, Args.size()); + return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); +} + +QualType Sema::ProduceCtorInitMemberSignatureHelp( + Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, + ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) { + if (!CodeCompleter) + return QualType(); + + CXXConstructorDecl *Constructor = + dyn_cast<CXXConstructorDecl>(ConstructorDecl); + if (!Constructor) + return QualType(); + // FIXME: Add support for Base class constructors as well. + if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl( + Constructor->getParent(), SS, TemplateTypeTy, II)) + return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(), + MemberDecl->getLocation(), ArgExprs, + OpenParLoc); + return QualType(); } void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { @@ -4602,7 +4792,12 @@ void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { return; } - CodeCompleteExpression(S, VD->getType()); + CodeCompleteExpressionData Data; + Data.PreferredType = VD->getType(); + // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'. + Data.IgnoreDecls.push_back(VD); + + CodeCompleteExpression(S, Data); } void Sema::CodeCompleteReturn(Scope *S) { @@ -4610,9 +4805,9 @@ void Sema::CodeCompleteReturn(Scope *S) { if (isa<BlockDecl>(CurContext)) { if (BlockScopeInfo *BSI = getCurBlock()) ResultType = BSI->ReturnType; - } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext)) + } else if (const auto *Function = dyn_cast<FunctionDecl>(CurContext)) ResultType = Function->getReturnType(); - else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext)) + else if (const auto *Method = dyn_cast<ObjCMethodDecl>(CurContext)) ResultType = Method->getReturnType(); if (ResultType.isNull()) @@ -4676,21 +4871,99 @@ void Sema::CodeCompleteAfterIf(Scope *S) { AddPrettyFunctionResults(getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), - Results.data(),Results.size()); + Results.data(), Results.size()); +} + +static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS, + tok::TokenKind Op) { + if (!LHS) + return QualType(); + + QualType LHSType = LHS->getType(); + if (LHSType->isPointerType()) { + if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal) + return S.getASTContext().getPointerDiffType(); + // Pointer difference is more common than subtracting an int from a pointer. + if (Op == tok::minus) + return LHSType; + } + + switch (Op) { + // No way to infer the type of RHS from LHS. + case tok::comma: + return QualType(); + // Prefer the type of the left operand for all of these. + // Arithmetic operations. + case tok::plus: + case tok::plusequal: + case tok::minus: + case tok::minusequal: + case tok::percent: + case tok::percentequal: + case tok::slash: + case tok::slashequal: + case tok::star: + case tok::starequal: + // Assignment. + case tok::equal: + // Comparison operators. + case tok::equalequal: + case tok::exclaimequal: + case tok::less: + case tok::lessequal: + case tok::greater: + case tok::greaterequal: + case tok::spaceship: + return LHS->getType(); + // Binary shifts are often overloaded, so don't try to guess those. + case tok::greatergreater: + case tok::greatergreaterequal: + case tok::lessless: + case tok::lesslessequal: + if (LHSType->isIntegralOrEnumerationType()) + return S.getASTContext().IntTy; + return QualType(); + // Logical operators, assume we want bool. + case tok::ampamp: + case tok::pipepipe: + case tok::caretcaret: + return S.getASTContext().BoolTy; + // Operators often used for bit manipulation are typically used with the type + // of the left argument. + case tok::pipe: + case tok::pipeequal: + case tok::caret: + case tok::caretequal: + case tok::amp: + case tok::ampequal: + if (LHSType->isIntegralOrEnumerationType()) + return LHSType; + return QualType(); + // RHS should be a pointer to a member of the 'LHS' type, but we can't give + // any particular type here. + case tok::periodstar: + case tok::arrowstar: + return QualType(); + default: + // FIXME(ibiryukov): handle the missing op, re-add the assertion. + // assert(false && "unhandled binary op"); + return QualType(); + } } -void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) { - if (LHS) - CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType()); +void Sema::CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op) { + auto PreferredType = getPreferredTypeOfBinaryRHS(*this, LHS, Op); + if (!PreferredType.isNull()) + CodeCompleteExpression(S, PreferredType); else CodeCompleteOrdinaryName(S, PCC_Expression); } void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, - bool EnteringContext) { + bool EnteringContext, QualType BaseType) { if (SS.isEmpty() || !CodeCompleter) return; @@ -4699,7 +4972,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, // it can be useful for global code completion which have information about // contexts/symbols that are not in the AST. if (SS.isInvalid()) { - CodeCompletionContext CC(CodeCompletionContext::CCC_Name); + CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol); CC.setCXXScopeSpecifier(SS); HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0); return; @@ -4717,7 +4990,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_Name); + CodeCompletionContext::CCC_Symbol); Results.EnterNewScope(); // The "template" keyword can follow "::" in the grammar, but only @@ -4737,7 +5010,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, if (CodeCompleter->includeNamespaceLevelDecls() || (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) { - CodeCompletionDeclConsumer Consumer(Results, CurContext); + CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType); LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, /*IncludeGlobalScope=*/true, /*IncludeDependentBases=*/true, @@ -4757,7 +5030,10 @@ void Sema::CodeCompleteUsing(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_PotentiallyQualifiedName, + // This can be both a using alias or using + // declaration, in the former we expect a new name and a + // symbol in the latter case. + CodeCompletionContext::CCC_SymbolOrNewName, &ResultBuilder::IsNestedNameSpecifier); Results.EnterNewScope(); @@ -4797,7 +5073,7 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { Results.data(), Results.size()); } -void Sema::CodeCompleteNamespaceDecl(Scope *S) { +void Sema::CodeCompleteNamespaceDecl(Scope *S) { if (!CodeCompleter) return; @@ -4805,14 +5081,14 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { if (!S->getParent()) Ctx = Context.getTranslationUnitDecl(); - bool SuppressedGlobalResults - = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); + bool SuppressedGlobalResults = + Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), SuppressedGlobalResults - ? CodeCompletionContext::CCC_Namespace - : CodeCompletionContext::CCC_Other, + ? CodeCompletionContext::CCC_Namespace + : CodeCompletionContext::CCC_Other, &ResultBuilder::IsNamespace); if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { @@ -4822,7 +5098,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { // definition of each namespace. std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest; for (DeclContext::specific_decl_iterator<NamespaceDecl> - NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end()); + NS(Ctx->decls_begin()), + NSEnd(Ctx->decls_end()); NS != NSEnd; ++NS) OrigToLatest[NS->getOriginalNamespace()] = *NS; @@ -4830,22 +5107,21 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { // namespace to the list of results. Results.EnterNewScope(); for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator - NS = OrigToLatest.begin(), - NSEnd = OrigToLatest.end(); + NS = OrigToLatest.begin(), + NSEnd = OrigToLatest.end(); NS != NSEnd; ++NS) - Results.AddResult(CodeCompletionResult( - NS->second, Results.getBasePriority(NS->second), - nullptr), - CurContext, nullptr, false); + Results.AddResult( + CodeCompletionResult(NS->second, Results.getBasePriority(NS->second), + nullptr), + CurContext, nullptr, false); Results.ExitScope(); } - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } -void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { +void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { if (!CodeCompleter) return; @@ -4858,9 +5134,8 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { LookupVisibleDecls(S, LookupOrdinaryName, Consumer, CodeCompleter->includeGlobals(), CodeCompleter->loadExternal()); - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteOperatorName(Scope *S) { @@ -4875,8 +5150,8 @@ void Sema::CodeCompleteOperatorName(Scope *S) { Results.EnterNewScope(); // Add the names of overloadable operators. -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - if (std::strcmp(Spelling, "?")) \ +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + if (std::strcmp(Spelling, "?")) \ Results.AddResult(Result(Spelling)); #include "clang/Basic/OperatorKinds.def" @@ -4896,20 +5171,19 @@ void Sema::CodeCompleteOperatorName(Scope *S) { } void Sema::CodeCompleteConstructorInitializer( - Decl *ConstructorD, - ArrayRef <CXXCtorInitializer *> Initializers) { + Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) { if (!ConstructorD) return; AdjustDeclIfTemplate(ConstructorD); - CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD); + auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD); if (!Constructor) return; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_PotentiallyQualifiedName); + CodeCompletionContext::CCC_Symbol); Results.EnterNewScope(); // Fill in any already-initialized fields or base classes. @@ -4917,39 +5191,96 @@ void Sema::CodeCompleteConstructorInitializer( llvm::SmallPtrSet<CanQualType, 4> InitializedBases; for (unsigned I = 0, E = Initializers.size(); I != E; ++I) { if (Initializers[I]->isBaseInitializer()) - InitializedBases.insert( - Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0))); + InitializedBases.insert(Context.getCanonicalType( + QualType(Initializers[I]->getBaseClass(), 0))); else - InitializedFields.insert(cast<FieldDecl>( - Initializers[I]->getAnyMember())); + InitializedFields.insert( + cast<FieldDecl>(Initializers[I]->getAnyMember())); } // Add completions for base classes. - CodeCompletionBuilder Builder(Results.getAllocator(), - Results.getCodeCompletionTUInfo()); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); bool SawLastInitializer = Initializers.empty(); CXXRecordDecl *ClassDecl = Constructor->getParent(); + + auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk(Name); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (const auto *Function = dyn_cast<FunctionDecl>(ND)) + AddFunctionParameterChunks(PP, Policy, Function, Builder); + else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND)) + AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(), + Builder); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + return Builder.TakeString(); + }; + auto AddDefaultCtorInit = [&](const char *Name, const char *Type, + const NamedDecl *ND) { + CodeCompletionBuilder Builder(Results.getAllocator(), + Results.getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk(Name); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk(Type); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + if (ND) { + auto CCR = CodeCompletionResult( + Builder.TakeString(), ND, + SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration); + if (isa<FieldDecl>(ND)) + CCR.CursorKind = CXCursor_MemberRef; + return Results.AddResult(CCR); + } + return Results.AddResult(CodeCompletionResult( + Builder.TakeString(), + SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration)); + }; + auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority, + const char *Name, const FieldDecl *FD) { + if (!RD) + return AddDefaultCtorInit(Name, + FD ? Results.getAllocator().CopyString( + FD->getType().getAsString(Policy)) + : Name, + FD); + auto Ctors = getConstructors(Context, RD); + if (Ctors.begin() == Ctors.end()) + return AddDefaultCtorInit(Name, Name, RD); + for (const NamedDecl *Ctor : Ctors) { + auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority); + CCR.CursorKind = getCursorKindForDecl(Ctor); + Results.AddResult(CCR); + } + }; + auto AddBase = [&](const CXXBaseSpecifier &Base) { + const char *BaseName = + Results.getAllocator().CopyString(Base.getType().getAsString(Policy)); + const auto *RD = Base.getType()->getAsCXXRecordDecl(); + AddCtorsWithName( + RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, + BaseName, nullptr); + }; + auto AddField = [&](const FieldDecl *FD) { + const char *FieldName = + Results.getAllocator().CopyString(FD->getIdentifier()->getName()); + const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl(); + AddCtorsWithName( + RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, + FieldName, FD); + }; + for (const auto &Base : ClassDecl->bases()) { if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) .second) { - SawLastInitializer - = !Initializers.empty() && - Initializers.back()->isBaseInitializer() && - Context.hasSameUnqualifiedType(Base.getType(), - QualType(Initializers.back()->getBaseClass(), 0)); + SawLastInitializer = + !Initializers.empty() && Initializers.back()->isBaseInitializer() && + Context.hasSameUnqualifiedType( + Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } - Builder.AddTypedTextChunk( - Results.getAllocator().CopyString( - Base.getType().getAsString(Policy))); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("args"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - SawLastInitializer? CCP_NextInitializer - : CCP_MemberDeclaration)); + AddBase(Base); SawLastInitializer = false; } @@ -4957,23 +5288,14 @@ void Sema::CodeCompleteConstructorInitializer( for (const auto &Base : ClassDecl->vbases()) { if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) .second) { - SawLastInitializer - = !Initializers.empty() && - Initializers.back()->isBaseInitializer() && - Context.hasSameUnqualifiedType(Base.getType(), - QualType(Initializers.back()->getBaseClass(), 0)); + SawLastInitializer = + !Initializers.empty() && Initializers.back()->isBaseInitializer() && + Context.hasSameUnqualifiedType( + Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); continue; } - Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString( - Base.getType().getAsString(Policy))); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("args"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - SawLastInitializer? CCP_NextInitializer - : CCP_MemberDeclaration)); + AddBase(Base); SawLastInitializer = false; } @@ -4981,27 +5303,16 @@ void Sema::CodeCompleteConstructorInitializer( for (auto *Field : ClassDecl->fields()) { if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl())) .second) { - SawLastInitializer - = !Initializers.empty() && - Initializers.back()->isAnyMemberInitializer() && - Initializers.back()->getAnyMember() == Field; + SawLastInitializer = !Initializers.empty() && + Initializers.back()->isAnyMemberInitializer() && + Initializers.back()->getAnyMember() == Field; continue; } if (!Field->getDeclName()) continue; - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Field->getIdentifier()->getName())); - Builder.AddChunk(CodeCompletionString::CK_LeftParen); - Builder.AddPlaceholderChunk("args"); - Builder.AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - SawLastInitializer? CCP_NextInitializer - : CCP_MemberDeclaration, - CXCursor_MemberRef, - CXAvailability_Available, - Field)); + AddField(Field); SawLastInitializer = false; } Results.ExitScope(); @@ -5042,9 +5353,7 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, for (; S && !isNamespaceScope(S); S = S->getParent()) { for (const auto *D : S->decls()) { const auto *Var = dyn_cast<VarDecl>(D); - if (!Var || - !Var->hasLocalStorage() || - Var->hasAttr<BlocksAttr>()) + if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>()) continue; if (Known.insert(Var->getIdentifier()).second) @@ -5065,26 +5374,25 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, /// Macro that optionally prepends an "@" to the string literal passed in via /// Keyword, depending on whether NeedAt is true or false. -#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword) +#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword) static void AddObjCImplementationResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt) { + ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; // Since we have an implementation, we can end it. - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end"))); CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); - if (LangOpts.ObjC2) { + if (LangOpts.ObjC) { // @dynamic - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("property"); Results.AddResult(Result(Builder.TakeString())); // @synthesize - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("property"); Results.AddResult(Result(Builder.TakeString())); @@ -5092,22 +5400,21 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts, } static void AddObjCInterfaceResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt) { + ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; // Since we have an interface or protocol, we can end it. - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end"))); - if (LangOpts.ObjC2) { + if (LangOpts.ObjC) { // @property - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property"))); // @required - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required"))); // @optional - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional"))); } } @@ -5117,7 +5424,7 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { Results.getCodeCompletionTUInfo()); // @class name ; - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("name"); Results.AddResult(Result(Builder.TakeString())); @@ -5126,26 +5433,27 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { // @interface name // FIXME: Could introduce the whole pattern, including superclasses and // such. - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("class"); Results.AddResult(Result(Builder.TakeString())); // @protocol name - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("protocol"); Results.AddResult(Result(Builder.TakeString())); // @implementation name - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("class"); Results.AddResult(Result(Builder.TakeString())); } // @compatibility_alias name - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias")); + Builder.AddTypedTextChunk( + OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("alias"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -5188,7 +5496,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { Results.getSema().getLangOpts().ConstStrings) EncodeType = "const char[]"; Builder.AddResultTypeChunk(EncodeType); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("type-name"); Builder.AddChunk(CodeCompletionString::CK_RightParen); @@ -5196,7 +5504,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { // @protocol ( protocol-name ) Builder.AddResultTypeChunk("Protocol *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("protocol-name"); Builder.AddChunk(CodeCompletionString::CK_RightParen); @@ -5204,7 +5512,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { // @selector ( selector ) Builder.AddResultTypeChunk("SEL"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector")); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("selector"); Builder.AddChunk(CodeCompletionString::CK_RightParen); @@ -5212,21 +5520,21 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { // @"string" Builder.AddResultTypeChunk("NSString *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\"")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\"")); Builder.AddPlaceholderChunk("string"); Builder.AddTextChunk("\""); Results.AddResult(Result(Builder.TakeString())); // @[objects, ...] Builder.AddResultTypeChunk("NSArray *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"[")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "[")); Builder.AddPlaceholderChunk("objects, ..."); Builder.AddChunk(CodeCompletionString::CK_RightBracket); Results.AddResult(Result(Builder.TakeString())); // @{key : object, ...} Builder.AddResultTypeChunk("NSDictionary *"); - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{")); Builder.AddPlaceholderChunk("key"); Builder.AddChunk(CodeCompletionString::CK_Colon); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -5250,7 +5558,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { if (Results.includeCodePatterns()) { // @try { statements } @catch ( declaration ) { statements } @finally // { statements } - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try")); Builder.AddChunk(CodeCompletionString::CK_LeftBrace); Builder.AddPlaceholderChunk("statements"); Builder.AddChunk(CodeCompletionString::CK_RightBrace); @@ -5269,14 +5577,14 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { } // @throw - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("expression"); Results.AddResult(Result(Builder.TakeString())); if (Results.includeCodePatterns()) { // @synchronized ( expression ) { statements } - Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized")); + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized")); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddChunk(CodeCompletionString::CK_LeftParen); Builder.AddPlaceholderChunk("expression"); @@ -5289,14 +5597,13 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { } static void AddObjCVisibilityResults(const LangOptions &LangOpts, - ResultBuilder &Results, - bool NeedAt) { + ResultBuilder &Results, bool NeedAt) { typedef CodeCompletionResult Result; - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private"))); - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected"))); - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public"))); - if (LangOpts.ObjC2) - Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected"))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public"))); + if (LangOpts.ObjC) + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package"))); } void Sema::CodeCompleteObjCAtVisibility(Scope *S) { @@ -5348,14 +5655,12 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { return true; // Check for more than one of { assign, copy, retain, strong, weak }. - unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_retain | - ObjCDeclSpec::DQ_PR_strong | - ObjCDeclSpec::DQ_PR_weak); - if (AssignCopyRetMask && - AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && + unsigned AssignCopyRetMask = + Attributes & + (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak); + if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain && @@ -5433,11 +5738,10 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { enum ObjCMethodKind { MK_Any, ///< Any kind of method, provided it means other specified criteria. MK_ZeroArgSelector, ///< Zero-argument (unary) selector. - MK_OneArgSelector ///< One-argument selector. + MK_OneArgSelector ///< One-argument selector. }; -static bool isAcceptableObjCSelector(Selector Sel, - ObjCMethodKind WantKind, +static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind, ArrayRef<IdentifierInfo *> SelIdents, bool AllowSameLength = true) { unsigned NumSelIdents = SelIdents.size(); @@ -5445,9 +5749,12 @@ static bool isAcceptableObjCSelector(Selector Sel, return false; switch (WantKind) { - case MK_Any: break; - case MK_ZeroArgSelector: return Sel.isUnarySelector(); - case MK_OneArgSelector: return Sel.getNumArgs() == 1; + case MK_Any: + break; + case MK_ZeroArgSelector: + return Sel.isUnarySelector(); + case MK_OneArgSelector: + return Sel.getNumArgs() == 1; } if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs()) @@ -5468,11 +5775,9 @@ static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, AllowSameLength); } -namespace { - /// A set of selectors, which is used to avoid introducing multiple - /// completions with the same selector into the result set. - typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet; -} +/// A set of selectors, which is used to avoid introducing multiple +/// completions with the same selector into the result set. +typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet; /// Add all of the Objective-C methods in the given Objective-C /// container to the set of results. @@ -5505,7 +5810,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, Container = getContainerDef(Container); ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass()); - for (auto *M : Container->methods()) { + for (ObjCMethodDecl *M : Container->methods()) { // The instance methods on the root class can be messaged via the // metaclass. if (M->isInstanceMethod() == WantInstanceMethods || @@ -5522,16 +5827,16 @@ static void AddObjCMethods(ObjCContainerDecl *Container, R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = (WantKind != MK_Any); if (!InOriginalClass) - R.Priority += CCD_InBaseClass; + setInBaseClass(R); Results.MaybeAddResult(R, CurContext); } } // Visit the protocols of protocols. - if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { if (Protocol->hasDefinition()) { - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + Protocol->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -5544,19 +5849,19 @@ static void AddObjCMethods(ObjCContainerDecl *Container, return; // Add methods in protocols. - for (auto *I : IFace->protocols()) + for (ObjCProtocolDecl *I : IFace->protocols()) AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext, Selectors, AllowSameLength, Results, false, IsRootClass); // Add methods in categories. - for (auto *CatDecl : IFace->known_categories()) { + for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) { AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, CurContext, Selectors, AllowSameLength, Results, InOriginalClass, IsRootClass); // Add a categories protocol methods. - const ObjCList<ObjCProtocolDecl> &Protocols - = CatDecl->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + CatDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -5584,13 +5889,12 @@ static void AddObjCMethods(ObjCContainerDecl *Container, IsRootClass); } - void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { // Try to find the interface where getters might live. ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); if (!Class) { - if (ObjCCategoryDecl *Category - = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) + if (ObjCCategoryDecl *Category = + dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) Class = Category->getClassInterface(); if (!Class) @@ -5613,11 +5917,10 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { void Sema::CodeCompleteObjCPropertySetter(Scope *S) { // Try to find the interface where setters might live. - ObjCInterfaceDecl *Class - = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); + ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); if (!Class) { - if (ObjCCategoryDecl *Category - = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) + if (ObjCCategoryDecl *Category = + dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) Class = Category->getClassInterface(); if (!Class) @@ -5631,8 +5934,8 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) { Results.EnterNewScope(); VisitedSelectorSet Selectors; - AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, - Selectors, /*AllowSameLength=*/true, Results); + AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors, + /*AllowSameLength=*/true, Results); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -5663,9 +5966,9 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, if ((DS.getObjCDeclQualifier() & (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref | ObjCDeclSpec::DQ_Oneway)) == 0) { - Results.AddResult("bycopy"); - Results.AddResult("byref"); - Results.AddResult("oneway"); + Results.AddResult("bycopy"); + Results.AddResult("byref"); + Results.AddResult("oneway"); } if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) { Results.AddResult("nonnull"); @@ -5710,7 +6013,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, CodeCompleter->loadExternal()); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); @@ -5721,7 +6024,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, /// common uses of Objective-C. This routine returns that class type, /// or NULL if no better result could be determined. static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { - ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E); + auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E); if (!Msg) return nullptr; @@ -5741,8 +6044,8 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { ObjCInterfaceDecl *IFace = nullptr; switch (Msg->getReceiverKind()) { case ObjCMessageExpr::Class: - if (const ObjCObjectType *ObjType - = Msg->getClassReceiver()->getAs<ObjCObjectType>()) + if (const ObjCObjectType *ObjType = + Msg->getClassReceiver()->getAs<ObjCObjectType>()) IFace = ObjType->getInterface(); break; @@ -5764,27 +6067,27 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { ObjCInterfaceDecl *Super = IFace->getSuperClass(); if (Method->isInstanceMethod()) return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) - .Case("retain", IFace) - .Case("strong", IFace) - .Case("autorelease", IFace) - .Case("copy", IFace) - .Case("copyWithZone", IFace) - .Case("mutableCopy", IFace) - .Case("mutableCopyWithZone", IFace) - .Case("awakeFromCoder", IFace) - .Case("replacementObjectFromCoder", IFace) + .Case("retain", IFace) + .Case("strong", IFace) + .Case("autorelease", IFace) + .Case("copy", IFace) + .Case("copyWithZone", IFace) + .Case("mutableCopy", IFace) + .Case("mutableCopyWithZone", IFace) + .Case("awakeFromCoder", IFace) + .Case("replacementObjectFromCoder", IFace) + .Case("class", IFace) + .Case("classForCoder", IFace) + .Case("superclass", Super) + .Default(nullptr); + + return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) + .Case("new", IFace) + .Case("alloc", IFace) + .Case("allocWithZone", IFace) .Case("class", IFace) - .Case("classForCoder", IFace) .Case("superclass", Super) .Default(nullptr); - - return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) - .Case("new", IFace) - .Case("alloc", IFace) - .Case("allocWithZone", IFace) - .Case("class", IFace) - .Case("superclass", Super) - .Default(nullptr); } // Add a special completion for a message send to "super", which fills in the @@ -5803,10 +6106,10 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { /// /// \returns the Objective-C method declaration that would be invoked by /// this "super" completion. If NULL, no completion was added. -static ObjCMethodDecl *AddSuperSendCompletion( - Sema &S, bool NeedSuperKeyword, - ArrayRef<IdentifierInfo *> SelIdents, - ResultBuilder &Results) { +static ObjCMethodDecl * +AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, + ArrayRef<IdentifierInfo *> SelIdents, + ResultBuilder &Results) { ObjCMethodDecl *CurMethod = S.getCurMethodDecl(); if (!CurMethod) return nullptr; @@ -5826,7 +6129,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( if (!SuperMethod) { for (const auto *Cat : Class->known_categories()) { if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(), - CurMethod->isInstanceMethod()))) + CurMethod->isInstanceMethod()))) break; } } @@ -5841,8 +6144,8 @@ static ObjCMethodDecl *AddSuperSendCompletion( return nullptr; for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(), - CurPEnd = CurMethod->param_end(), - SuperP = SuperMethod->param_begin(); + CurPEnd = CurMethod->param_end(), + SuperP = SuperMethod->param_begin(); CurP != CurPEnd; ++CurP, ++SuperP) { // Make sure the parameter types are compatible. if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), @@ -5860,8 +6163,7 @@ static ObjCMethodDecl *AddSuperSendCompletion( // Give this completion a return type. AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, - Results.getCompletionContext().getBaseType(), - Builder); + Results.getCompletionContext().getBaseType(), Builder); // If we need the "super" keyword, add it (plus some spacing). if (NeedSuperKeyword) { @@ -5872,11 +6174,11 @@ static ObjCMethodDecl *AddSuperSendCompletion( Selector Sel = CurMethod->getSelector(); if (Sel.isUnarySelector()) { if (NeedSuperKeyword) - Builder.AddTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); else - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); } else { ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { @@ -5885,20 +6187,17 @@ static ObjCMethodDecl *AddSuperSendCompletion( if (I < SelIdents.size()) Builder.AddInformativeChunk( - Builder.getAllocator().CopyString( - Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); else if (NeedSuperKeyword || I > SelIdents.size()) { Builder.AddTextChunk( - Builder.getAllocator().CopyString( - Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( - (*CurP)->getIdentifier()->getName())); + (*CurP)->getIdentifier()->getName())); } else { Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString( - Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( - (*CurP)->getIdentifier()->getName())); + (*CurP)->getIdentifier()->getName())); } } } @@ -5910,12 +6209,13 @@ static ObjCMethodDecl *AddSuperSendCompletion( void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { typedef CodeCompletionResult Result; - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext::CCC_ObjCMessageReceiver, - getLangOpts().CPlusPlus11 - ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture - : &ResultBuilder::IsObjCMessageReceiver); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_ObjCMessageReceiver, + getLangOpts().CPlusPlus11 + ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture + : &ResultBuilder::IsObjCMessageReceiver); CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.EnterNewScope(); @@ -5939,10 +6239,9 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { Results.ExitScope(); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, false); + AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); - } void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, @@ -5965,8 +6264,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // send [super ...] is actually calling an instance method on the // current object. return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents, - AtArgumentExpression, - CDecl); + AtArgumentExpression, CDecl); } // Fall through to send to the superclass in CDecl. @@ -5974,13 +6272,12 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, // "super" may be the name of a type or variable. Figure out which // it is. IdentifierInfo *Super = getSuperIdentifier(); - NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, - LookupOrdinaryName); + NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName); if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) { // "super" names an interface. Use it. } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) { - if (const ObjCObjectType *Iface - = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>()) + if (const ObjCObjectType *Iface = + Context.getTypeDeclType(TD)->getAs<ObjCObjectType>()) CDecl = Iface->getInterface(); } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) { // "super" names an unresolved type; we can't be more specific. @@ -5990,11 +6287,10 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, SourceLocation TemplateKWLoc; UnqualifiedId id; id.setIdentifier(Super, SuperLoc); - ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, - false, false); + ExprResult SuperExpr = + ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), - SelIdents, - AtArgumentExpression); + SelIdents, AtArgumentExpression); } // Fall through @@ -6025,8 +6321,8 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, if (R.Priority <= BestPriority) { const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration); if (NumSelIdents <= Method->param_size()) { - QualType MyPreferredType = Method->parameters()[NumSelIdents - 1] - ->getType(); + QualType MyPreferredType = + Method->parameters()[NumSelIdents - 1]->getType(); if (R.Priority < BestPriority || PreferredType.isNull()) { BestPriority = R.Priority; PreferredType = MyPreferredType; @@ -6045,8 +6341,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, ArrayRef<IdentifierInfo *> SelIdents, - bool AtArgumentExpression, - bool IsSuper, + bool AtArgumentExpression, bool IsSuper, ResultBuilder &Results) { typedef CodeCompletionResult Result; ObjCInterfaceDecl *CDecl = nullptr; @@ -6067,8 +6362,8 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, // If this is a send-to-super, try to add the special "super" send // completion. if (IsSuper) { - if (ObjCMethodDecl *SuperMethod - = AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) + if (ObjCMethodDecl *SuperMethod = + AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) Results.Ignore(SuperMethod); } @@ -6079,9 +6374,8 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, VisitedSelectorSet Selectors; if (CDecl) - AddObjCMethods(CDecl, false, MK_Any, SelIdents, - SemaRef.CurContext, Selectors, AtArgumentExpression, - Results); + AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext, + Selectors, AtArgumentExpression, Results); else { // We're messaging "id" as a type; provide all class/factory methods. @@ -6100,11 +6394,10 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, } for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), - MEnd = SemaRef.MethodPool.end(); + MEnd = SemaRef.MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.second; - MethList && MethList->getMethod(); - MethList = MethList->getNext()) { + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; @@ -6127,10 +6420,11 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, QualType T = this->GetTypeFromParser(Receiver); - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, - T, SelIdents)); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T, + SelIdents)); AddClassMessageCompletions(*this, S, Receiver, SelIdents, AtArgumentExpression, IsSuper, Results); @@ -6141,8 +6435,8 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, // code-complete the expression using the corresponding parameter type as // our preferred type, improving completion results. if (AtArgumentExpression) { - QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, - SelIdents.size()); + QualType PreferredType = + getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); else @@ -6150,8 +6444,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, return; } - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); } @@ -6171,10 +6464,11 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, return; RecExpr = Conv.get(); } - QualType ReceiverType = RecExpr? RecExpr->getType() - : Super? Context.getObjCObjectPointerType( + QualType ReceiverType = RecExpr + ? RecExpr->getType() + : Super ? Context.getObjCObjectPointerType( Context.getObjCInterfaceType(Super)) - : Context.getObjCIdType(); + : Context.getObjCIdType(); // If we're messaging an expression with type "id" or "Class", check // whether we know something special about the receiver that allows @@ -6182,13 +6476,12 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) { if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) { if (ReceiverType->isObjCClassType()) - return CodeCompleteObjCClassMessage(S, - ParsedType::make(Context.getObjCInterfaceType(IFace)), - SelIdents, - AtArgumentExpression, Super); + return CodeCompleteObjCClassMessage( + S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents, + AtArgumentExpression, Super); - ReceiverType = Context.getObjCObjectPointerType( - Context.getObjCInterfaceType(IFace)); + ReceiverType = + Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace)); } } else if (RecExpr && getLangOpts().CPlusPlus) { ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr); @@ -6199,18 +6492,19 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, } // Build the set of methods we can see. - ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, - ReceiverType, SelIdents)); + ResultBuilder Results( + *this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, + ReceiverType, SelIdents)); Results.EnterNewScope(); // If this is a send-to-super, try to add the special "super" send // completion. if (Super) { - if (ObjCMethodDecl *SuperMethod - = AddSuperSendCompletion(*this, false, SelIdents, Results)) + if (ObjCMethodDecl *SuperMethod = + AddSuperSendCompletion(*this, false, SelIdents, Results)) Results.Ignore(SuperMethod); } @@ -6229,30 +6523,29 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, ReceiverType->isObjCQualifiedClassType()) { if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) - AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, - CurContext, Selectors, AtArgumentExpression, Results); + AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext, + Selectors, AtArgumentExpression, Results); } } // Handle messages to a qualified ID ("id<foo>"). - else if (const ObjCObjectPointerType *QualID - = ReceiverType->getAsObjCQualifiedIdType()) { + else if (const ObjCObjectPointerType *QualID = + ReceiverType->getAsObjCQualifiedIdType()) { // Search protocols for instance methods. for (auto *I : QualID->quals()) - AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, - Selectors, AtArgumentExpression, Results); + AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, + AtArgumentExpression, Results); } // Handle messages to a pointer to interface type. - else if (const ObjCObjectPointerType *IFacePtr - = ReceiverType->getAsObjCInterfacePointerType()) { + else if (const ObjCObjectPointerType *IFacePtr = + ReceiverType->getAsObjCInterfacePointerType()) { // Search the class, its superclasses, etc., for instance methods. AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, - CurContext, Selectors, AtArgumentExpression, - Results); + CurContext, Selectors, AtArgumentExpression, Results); // Search protocols for instance methods. for (auto *I : IFacePtr->quals()) - AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, - Selectors, AtArgumentExpression, Results); + AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, + AtArgumentExpression, Results); } // Handle messages to "id". else if (ReceiverType->isObjCIdType()) { @@ -6276,8 +6569,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, MEnd = MethodPool.end(); M != MEnd; ++M) { for (ObjCMethodList *MethList = &M->second.first; - MethList && MethList->getMethod(); - MethList = MethList->getNext()) { + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; @@ -6294,15 +6586,14 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, } Results.ExitScope(); - // If we're actually at the argument expression (rather than prior to the // selector), we're actually performing code completion for an expression. // Determine whether we have a single, best method. If so, we can // code-complete the expression using the corresponding parameter type as // our preferred type, improving completion results. if (AtArgumentExpression) { - QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, - SelIdents.size()); + QualType PreferredType = + getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); if (PreferredType.isNull()) CodeCompleteOrdinaryName(S, PCC_Expression); else @@ -6310,9 +6601,8 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, return; } - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), - Results.data(),Results.size()); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); } void Sema::CodeCompleteObjCForCollection(Scope *S, @@ -6336,8 +6626,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, // If we have an external source, load the entire class method // pool from the AST file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); - I != N; ++I) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; + ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || MethodPool.count(Sel)) continue; @@ -6351,7 +6641,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, CodeCompletionContext::CCC_SelectorName); Results.EnterNewScope(); for (GlobalMethodPool::iterator M = MethodPool.begin(), - MEnd = MethodPool.end(); + MEnd = MethodPool.end(); M != MEnd; ++M) { Selector Sel = M->first; @@ -6361,8 +6651,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); if (Sel.isUnarySelector()) { - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); Results.AddResult(Builder.TakeString()); continue; } @@ -6371,8 +6661,8 @@ void Sema::CodeCompleteObjCSelector(Scope *S, for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { if (I == SelIdents.size()) { if (!Accumulator.empty()) { - Builder.AddInformativeChunk(Builder.getAllocator().CopyString( - Accumulator)); + Builder.AddInformativeChunk( + Builder.getAllocator().CopyString(Accumulator)); Accumulator.clear(); } } @@ -6380,7 +6670,7 @@ void Sema::CodeCompleteObjCSelector(Scope *S, Accumulator += Sel.getNameForSlot(I); Accumulator += ':'; } - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator)); + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator)); Results.AddResult(Builder.TakeString()); } Results.ExitScope(); @@ -6400,13 +6690,14 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, // Record any protocols we find. if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D)) if (!OnlyForwardDeclarations || !Proto->hasDefinition()) - Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr), - CurContext, nullptr, false); + Results.AddResult( + Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext, + nullptr, false); } } void Sema::CodeCompleteObjCProtocolReferences( - ArrayRef<IdentifierLocPair> Protocols) { + ArrayRef<IdentifierLocPair> Protocols) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCProtocolName); @@ -6418,8 +6709,7 @@ void Sema::CodeCompleteObjCProtocolReferences( // already seen. // FIXME: This doesn't work when caching code-completion results. for (const IdentifierLocPair &Pair : Protocols) - if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, - Pair.second)) + if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second)) Results.Ignore(Protocol); // Add all protocols. @@ -6465,8 +6755,9 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D)) if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && (!OnlyUnimplemented || !Class->getImplementation())) - Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr), - CurContext, nullptr, false); + Results.AddResult( + Result(Class, Results.getBasePriority(Class), nullptr), CurContext, + nullptr, false); } } @@ -6496,8 +6787,8 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, Results.EnterNewScope(); // Make sure that we ignore the class we're currently defining. - NamedDecl *CurClass - = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + NamedDecl *CurClass = + LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); if (CurClass && isa<ObjCInterfaceDecl>(CurClass)) Results.Ignore(CurClass); @@ -6543,9 +6834,10 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, // Ignore any categories we find that have already been implemented by this // interface. llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; - NamedDecl *CurClass - = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); - if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){ + NamedDecl *CurClass = + LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + if (ObjCInterfaceDecl *Class = + dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) { for (const auto *Cat : Class->visible_categories()) CategoryNames.insert(Cat->getIdentifier()); } @@ -6556,9 +6848,9 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, for (const auto *D : TU->decls()) if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D)) if (CategoryNames.insert(Category->getIdentifier()).second) - Results.AddResult(Result(Category, Results.getBasePriority(Category), - nullptr), - CurContext, nullptr, false); + Results.AddResult( + Result(Category, Results.getBasePriority(Category), nullptr), + CurContext, nullptr, false); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -6573,8 +6865,8 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, // Find the corresponding interface. If we couldn't find the interface, the // program itself is ill-formed. However, we'll try to be helpful still by // providing the list of all of the categories we know about. - NamedDecl *CurClass - = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + NamedDecl *CurClass = + LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass); if (!Class) return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); @@ -6609,15 +6901,13 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other); ResultBuilder Results(*this, CodeCompleter->getAllocator(), - CodeCompleter->getCodeCompletionTUInfo(), - CCContext); + CodeCompleter->getCodeCompletionTUInfo(), CCContext); // Figure out where this @synthesize lives. - ObjCContainerDecl *Container - = dyn_cast_or_null<ObjCContainerDecl>(CurContext); - if (!Container || - (!isa<ObjCImplementationDecl>(Container) && - !isa<ObjCCategoryImplDecl>(Container))) + ObjCContainerDecl *Container = + dyn_cast_or_null<ObjCContainerDecl>(CurContext); + if (!Container || (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) return; // Ignore any properties that have already been implemented. @@ -6629,8 +6919,8 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { // Add any properties that we find. AddedPropertiesSet AddedProperties; Results.EnterNewScope(); - if (ObjCImplementationDecl *ClassImpl - = dyn_cast<ObjCImplementationDecl>(Container)) + if (ObjCImplementationDecl *ClassImpl = + dyn_cast<ObjCImplementationDecl>(Container)) AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false, /*AllowNullaryMethods=*/false, CurContext, AddedProperties, Results); @@ -6645,37 +6935,37 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { Results.data(), Results.size()); } -void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName) { +void Sema::CodeCompleteObjCPropertySynthesizeIvar( + Scope *S, IdentifierInfo *PropertyName) { typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); // Figure out where this @synthesize lives. - ObjCContainerDecl *Container - = dyn_cast_or_null<ObjCContainerDecl>(CurContext); - if (!Container || - (!isa<ObjCImplementationDecl>(Container) && - !isa<ObjCCategoryImplDecl>(Container))) + ObjCContainerDecl *Container = + dyn_cast_or_null<ObjCContainerDecl>(CurContext); + if (!Container || (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) return; // Figure out which interface we're looking into. ObjCInterfaceDecl *Class = nullptr; - if (ObjCImplementationDecl *ClassImpl - = dyn_cast<ObjCImplementationDecl>(Container)) + if (ObjCImplementationDecl *ClassImpl = + dyn_cast<ObjCImplementationDecl>(Container)) Class = ClassImpl->getClassInterface(); else - Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl() - ->getClassInterface(); + Class = cast<ObjCCategoryImplDecl>(Container) + ->getCategoryDecl() + ->getClassInterface(); // Determine the type of the property we're synthesizing. QualType PropertyType = Context.getObjCIdType(); if (Class) { if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration( PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { - PropertyType - = Property->getType().getNonReferenceType().getUnqualifiedType(); + PropertyType = + Property->getType().getNonReferenceType().getUnqualifiedType(); // Give preference to ivars Results.setPreferredType(PropertyType); @@ -6690,7 +6980,7 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, NameWithPrefix += PropertyName->getName(); std::string NameWithSuffix = PropertyName->getName().str(); NameWithSuffix += '_'; - for(; Class; Class = Class->getSuperClass()) { + for (; Class; Class = Class->getSuperClass()) { for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; Ivar = Ivar->getNextIvar()) { Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr), @@ -6706,8 +6996,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Reduce the priority of this result by one, to give it a slight // advantage over other results whose names don't match so closely. if (Results.size() && - Results.data()[Results.size() - 1].Kind - == CodeCompletionResult::RK_Declaration && + Results.data()[Results.size() - 1].Kind == + CodeCompletionResult::RK_Declaration && Results.data()[Results.size() - 1].Declaration == Ivar) Results.data()[Results.size() - 1].Priority--; } @@ -6721,14 +7011,14 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, typedef CodeCompletionResult Result; CodeCompletionAllocator &Allocator = Results.getAllocator(); CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(), - Priority,CXAvailability_Available); + Priority, CXAvailability_Available); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); - Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, - Policy, Allocator)); + Builder.AddResultTypeChunk( + GetCompletionTypeString(PropertyType, Context, Policy, Allocator)); Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); - Results.AddResult(Result(Builder.TakeString(), Priority, - CXCursor_ObjCIvarDecl)); + Results.AddResult( + Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl)); } Results.ExitScope(); @@ -6739,8 +7029,9 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, // Mapping from selectors to the methods that implement that selector, along // with the "in original class" flag. -typedef llvm::DenseMap< - Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap; +typedef llvm::DenseMap<Selector, + llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>> + KnownMethodsMap; /// Find all of the methods that reside in the given container /// (and its superclasses, protocols, etc.) that meet the given @@ -6760,8 +7051,8 @@ static void FindImplementableMethods(ASTContext &Context, IFace = IFace->getDefinition(); Container = IFace; - const ObjCList<ObjCProtocolDecl> &Protocols - = IFace->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + IFace->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -6777,14 +7068,14 @@ static void FindImplementableMethods(ASTContext &Context, // Visit the superclass. if (IFace->getSuperClass()) FindImplementableMethods(Context, IFace->getSuperClass(), - WantInstanceMethods, ReturnType, - KnownMethods, false); + WantInstanceMethods, ReturnType, KnownMethods, + false); } if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { // Recurse into protocols. - const ObjCList<ObjCProtocolDecl> &Protocols - = Category->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + Category->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) @@ -6806,10 +7097,10 @@ static void FindImplementableMethods(ASTContext &Context, Container = Protocol; // Recurse into protocols. - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); + const ObjCList<ObjCProtocolDecl> &Protocols = + Protocol->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); + E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, KnownMethods, false); @@ -6832,8 +7123,7 @@ static void FindImplementableMethods(ASTContext &Context, /// Add the parenthesized return or parameter type chunk to a code /// completion string. -static void AddObjCPassingTypeChunk(QualType Type, - unsigned ObjCDeclQuals, +static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals, ASTContext &Context, const PrintingPolicy &Policy, CodeCompletionBuilder &Builder) { @@ -6841,15 +7131,14 @@ static void AddObjCPassingTypeChunk(QualType Type, std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type); if (!Quals.empty()) Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals)); - Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy, - Builder.getAllocator())); + Builder.AddTextChunk( + GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator())); Builder.AddChunk(CodeCompletionString::CK_RightParen); } /// Determine whether the given class is or inherits from a class by /// the given name. -static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, - StringRef Name) { +static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) { if (!Class) return false; @@ -6863,8 +7152,7 @@ static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, /// Key-Value Observing (KVO). static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, bool IsInstanceMethod, - QualType ReturnType, - ASTContext &Context, + QualType ReturnType, ASTContext &Context, VisitedSelectorSet &KnownSelectors, ResultBuilder &Results) { IdentifierInfo *PropName = Property->getIdentifier(); @@ -6889,7 +7177,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, const char *CopiedKey; KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key) - : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {} + : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {} operator const char *() { if (CopiedKey) @@ -6904,19 +7192,19 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, if (!UpperKey.empty()) UpperKey[0] = toUppercase(UpperKey[0]); - bool ReturnTypeMatchesProperty = ReturnType.isNull() || - Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), - Property->getType()); - bool ReturnTypeMatchesVoid - = ReturnType.isNull() || ReturnType->isVoidType(); + bool ReturnTypeMatchesProperty = + ReturnType.isNull() || + Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), + Property->getType()); + bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType(); // Add the normal accessor -(type)key. if (IsInstanceMethod && KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second && ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) { if (ReturnType.isNull()) - AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, - Context, Policy, Builder); + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, + Builder); Builder.AddTypedTextChunk(Key); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, @@ -6928,9 +7216,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, if (IsInstanceMethod && ((!ReturnType.isNull() && (ReturnType->isIntegerType() || ReturnType->isBooleanType())) || - (ReturnType.isNull() && - (Property->getType()->isIntegerType() || - Property->getType()->isBooleanType())))) { + (ReturnType.isNull() && (Property->getType()->isIntegerType() || + Property->getType()->isBooleanType())))) { std::string SelectorName = (Twine("is") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) @@ -6941,8 +7228,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddChunk(CodeCompletionString::CK_RightParen); } - Builder.AddTypedTextChunk( - Allocator.CopyString(SelectorId->getName())); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); } @@ -6960,11 +7246,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddChunk(CodeCompletionString::CK_RightParen); } - Builder.AddTypedTextChunk( - Allocator.CopyString(SelectorId->getName())); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); Builder.AddTypedTextChunk(":"); - AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, - Context, Policy, Builder); + AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, + Builder); Builder.AddTextChunk(Key); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, CXCursor_ObjCInstanceMethodDecl)); @@ -6976,8 +7261,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, unsigned IndexedSetterPriority = CCP_CodePattern; unsigned UnorderedGetterPriority = CCP_CodePattern; unsigned UnorderedSetterPriority = CCP_CodePattern; - if (const ObjCObjectPointerType *ObjCPointer - = Property->getType()->getAs<ObjCObjectPointerType>()) { + if (const auto *ObjCPointer = + Property->getType()->getAs<ObjCObjectPointerType>()) { if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) { // If this interface type is not provably derived from a known // collection, penalize the corresponding completions. @@ -7013,12 +7298,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddChunk(CodeCompletionString::CK_RightParen); } - Builder.AddTypedTextChunk( - Allocator.CopyString(SelectorId->getName())); - Results.AddResult(Result(Builder.TakeString(), - std::min(IndexedGetterPriority, - UnorderedGetterPriority), - CXCursor_ObjCInstanceMethodDecl)); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); + Results.AddResult( + Result(Builder.TakeString(), + std::min(IndexedGetterPriority, UnorderedGetterPriority), + CXCursor_ObjCInstanceMethodDecl)); } } @@ -7026,8 +7310,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // Add -(id)objectInKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { - std::string SelectorName - = (Twine("objectIn") + UpperKey + "AtIndex").str(); + std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7051,10 +7334,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && - ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() - ->getName() == "NSArray"))) { - std::string SelectorName - = (Twine(Property->getName()) + "AtIndexes").str(); + ReturnType->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl() + ->getName() == "NSArray"))) { + std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7076,10 +7359,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // Add -(void)getKey:(type **)buffer range:(NSRange)inRange if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("get") + UpperKey).str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName), - &Context.Idents.get("range") - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), + &Context.Idents.get("range")}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7110,10 +7391,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get("insertObject"), - &Context.Idents.get(SelectorName) - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"), + &Context.Idents.get(SelectorName)}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7142,10 +7421,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes if (IsInstanceMethod && ReturnTypeMatchesVoid) { std::string SelectorName = (Twine("insert") + UpperKey).str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName), - &Context.Idents.get("atIndexes") - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), + &Context.Idents.get("atIndexes")}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7172,8 +7449,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); + std::string SelectorName = + (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7194,8 +7471,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("remove") + UpperKey + "AtIndexes").str(); + std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7216,12 +7492,10 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName), - &Context.Idents.get("withObject") - }; + std::string SelectorName = + (Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), + &Context.Idents.get("withObject")}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7248,13 +7522,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName1 - = (Twine("replace") + UpperKey + "AtIndexes").str(); + std::string SelectorName1 = + (Twine("replace") + UpperKey + "AtIndexes").str(); std::string SelectorName2 = (Twine("with") + UpperKey).str(); - IdentifierInfo *SelectorIds[2] = { - &Context.Idents.get(SelectorName1), - &Context.Idents.get(SelectorName2) - }; + IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1), + &Context.Idents.get(SelectorName2)}; if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { if (ReturnType.isNull()) { @@ -7285,8 +7557,9 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && - ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() - ->getName() == "NSEnumerator"))) { + ReturnType->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl() + ->getName() == "NSEnumerator"))) { std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) @@ -7299,7 +7572,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, - CXCursor_ObjCInstanceMethodDecl)); + CXCursor_ObjCInstanceMethodDecl)); } } @@ -7322,9 +7595,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddPlaceholderChunk("object-type"); Builder.AddTextChunk(" *"); } else { - Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, - Policy, - Builder.getAllocator())); + Builder.AddTextChunk(GetCompletionTypeString( + ReturnType, Context, Policy, Builder.getAllocator())); } Builder.AddChunk(CodeCompletionString::CK_RightParen); Builder.AddTextChunk("object"); @@ -7336,8 +7608,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // Mutable unordered accessors // - (void)addKeyObject:(type *)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("add") + UpperKey + Twine("Object")).str(); + std::string SelectorName = + (Twine("add") + UpperKey + Twine("Object")).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7380,8 +7652,8 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // - (void)removeKeyObject:(type *)object if (IsInstanceMethod && ReturnTypeMatchesVoid) { - std::string SelectorName - = (Twine("remove") + UpperKey + Twine("Object")).str(); + std::string SelectorName = + (Twine("remove") + UpperKey + Twine("Object")).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { if (ReturnType.isNull()) { @@ -7449,10 +7721,11 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, (ReturnType.isNull() || (ReturnType->isObjCObjectPointerType() && ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && - ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() - ->getName() == "NSSet"))) { - std::string SelectorName - = (Twine("keyPathsForValuesAffecting") + UpperKey).str(); + ReturnType->getAs<ObjCObjectPointerType>() + ->getInterfaceDecl() + ->getName() == "NSSet"))) { + std::string SelectorName = + (Twine("keyPathsForValuesAffecting") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) .second) { @@ -7464,17 +7737,16 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, - CXCursor_ObjCClassMethodDecl)); + CXCursor_ObjCClassMethodDecl)); } } // + (BOOL)automaticallyNotifiesObserversForKey if (!IsInstanceMethod && - (ReturnType.isNull() || - ReturnType->isIntegerType() || + (ReturnType.isNull() || ReturnType->isIntegerType() || ReturnType->isBooleanType())) { - std::string SelectorName - = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); + std::string SelectorName = + (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) .second) { @@ -7486,7 +7758,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, - CXCursor_ObjCClassMethodDecl)); + CXCursor_ObjCClassMethodDecl)); } } } @@ -7498,8 +7770,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, QualType ReturnType = GetTypeFromParser(ReturnTy); Decl *IDecl = nullptr; if (CurContext->isObjCContainer()) { - ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); - IDecl = OCD; + ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); + IDecl = OCD; } // Determine where we should start searching for methods. ObjCContainerDecl *SearchDecl = nullptr; @@ -7508,8 +7780,8 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) { SearchDecl = Impl->getClassInterface(); IsInImplementation = true; - } else if (ObjCCategoryImplDecl *CatImpl - = dyn_cast<ObjCCategoryImplDecl>(D)) { + } else if (ObjCCategoryImplDecl *CatImpl = + dyn_cast<ObjCCategoryImplDecl>(D)) { SearchDecl = CatImpl->getCategoryDecl(); IsInImplementation = true; } else @@ -7523,15 +7795,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, if (!SearchDecl) { HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, - nullptr, 0); + CodeCompletionContext::CCC_Other, nullptr, 0); return; } // Find all of the methods that we could declare/implement here. KnownMethodsMap KnownMethods; - FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, - ReturnType, KnownMethods); + FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType, + KnownMethods); // Add declarations or definitions for each of the known methods. typedef CodeCompletionResult Result; @@ -7541,7 +7812,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, Results.EnterNewScope(); PrintingPolicy Policy = getCompletionPrintingPolicy(*this); for (KnownMethodsMap::iterator M = KnownMethods.begin(), - MEnd = KnownMethods.end(); + MEnd = KnownMethods.end(); M != MEnd; ++M) { ObjCMethodDecl *Method = M->second.getPointer(); CodeCompletionBuilder Builder(Results.getAllocator(), @@ -7558,21 +7829,20 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, if (ReturnType.isNull()) { QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context); AttributedType::stripOuterNullability(ResTy); - AddObjCPassingTypeChunk(ResTy, - Method->getObjCDeclQualifier(), Context, Policy, - Builder); + AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context, + Policy, Builder); } Selector Sel = Method->getSelector(); // Add the first part of the selector to the pattern. - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Sel.getNameForSlot(0))); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); // Add parameters to the pattern. unsigned I = 0; for (ObjCMethodDecl::param_iterator P = Method->param_begin(), - PEnd = Method->param_end(); + PEnd = Method->param_end(); P != PEnd; (void)++P, ++I) { // Add the part of the selector name. if (I == 0) @@ -7580,7 +7850,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, else if (I < Sel.getNumArgs()) { Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddTypedTextChunk( - Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); } else break; @@ -7590,16 +7860,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, ParamType = (*P)->getType(); else ParamType = (*P)->getOriginalType(); - ParamType = ParamType.substObjCTypeArgs(Context, {}, - ObjCSubstitutionContext::Parameter); + ParamType = ParamType.substObjCTypeArgs( + Context, {}, ObjCSubstitutionContext::Parameter); AttributedType::stripOuterNullability(ParamType); - AddObjCPassingTypeChunk(ParamType, - (*P)->getObjCDeclQualifier(), - Context, Policy, - Builder); + AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context, + Policy, Builder); if (IdentifierInfo *Id = (*P)->getIdentifier()) - Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); + Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName())); } if (Method->isVariadic()) { @@ -7627,25 +7895,24 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, } unsigned Priority = CCP_CodePattern; + auto R = Result(Builder.TakeString(), Method, Priority); if (!M->second.getInt()) - Priority += CCD_InBaseClass; - - Results.AddResult(Result(Builder.TakeString(), Method, Priority)); + setInBaseClass(R); + Results.AddResult(std::move(R)); } // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of // the properties in this class and its categories. - if (Context.getLangOpts().ObjC2) { + if (Context.getLangOpts().ObjC) { SmallVector<ObjCContainerDecl *, 4> Containers; Containers.push_back(SearchDecl); VisitedSelectorSet KnownSelectors; for (KnownMethodsMap::iterator M = KnownMethods.begin(), - MEnd = KnownMethods.end(); + MEnd = KnownMethods.end(); M != MEnd; ++M) KnownSelectors.insert(M->first); - ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl); if (!IFace) if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl)) @@ -7669,16 +7936,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, Results.data(), Results.size()); } -void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, - bool IsInstanceMethod, - bool AtParameterName, - ParsedType ReturnTy, - ArrayRef<IdentifierInfo *> SelIdents) { +void Sema::CodeCompleteObjCMethodDeclSelector( + Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy, + ArrayRef<IdentifierInfo *> SelIdents) { // If we have an external source, load the entire class method // pool from the AST file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); - I != N; ++I) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; + ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || MethodPool.count(Sel)) continue; @@ -7700,10 +7965,9 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, for (GlobalMethodPool::iterator M = MethodPool.begin(), MEnd = MethodPool.end(); M != MEnd; ++M) { - for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : - &M->second.second; - MethList && MethList->getMethod(); - MethList = MethList->getNext()) { + for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first + : &M->second.second; + MethList && MethList->getMethod(); MethList = MethList->getNext()) { if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) continue; @@ -7718,7 +7982,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - Param->getIdentifier()->getName())); + Param->getIdentifier()->getName())); Results.AddResult(Builder.TakeString()); } } @@ -7864,7 +8128,7 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { Builder.AddPlaceholderChunk("arguments"); Results.AddResult(Builder.TakeString()); - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { // #import "header" Builder.AddTypedTextChunk("import"); Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); @@ -7916,29 +8180,27 @@ void Sema::CodeCompletePreprocessorDirective(bool InConditional) { } void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { - CodeCompleteOrdinaryName(S, - S->getFnParent()? Sema::PCC_RecoveryInFunction - : Sema::PCC_Namespace); + CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction + : Sema::PCC_Namespace); } void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), - IsDefinition? CodeCompletionContext::CCC_MacroName - : CodeCompletionContext::CCC_MacroNameUse); + IsDefinition ? CodeCompletionContext::CCC_MacroName + : CodeCompletionContext::CCC_MacroNameUse); if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { // Add just the names of macros, not their arguments. CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); Results.EnterNewScope(); for (Preprocessor::macro_iterator M = PP.macro_begin(), - MEnd = PP.macro_end(); + MEnd = PP.macro_end(); M != MEnd; ++M) { - Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( - M->first->getName())); - Results.AddResult(CodeCompletionResult(Builder.TakeString(), - CCP_CodePattern, - CXCursor_MacroDefinition)); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(M->first->getName())); + Results.AddResult(CodeCompletionResult( + Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition)); } Results.ExitScope(); } else if (IsDefinition) { @@ -7955,9 +8217,11 @@ void Sema::CodeCompletePreprocessorExpression() { CodeCompletionContext::CCC_PreprocessorExpression); if (!CodeCompleter || CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, true); + AddMacroResults(PP, Results, + CodeCompleter ? CodeCompleter->loadExternal() : false, + true); - // defined (<macro>) + // defined (<macro>) Results.EnterNewScope(); CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); @@ -7984,10 +8248,118 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, // for the expanded tokens. } +// This handles completion inside an #include filename, e.g. #include <foo/ba +// We look for the directory "foo" under each directory on the include path, +// list its files, and reassemble the appropriate #include. +void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { + // RelDir should use /, but unescaped \ is possible on windows! + // Our completions will normalize to / for simplicity, this case is rare. + std::string RelDir = llvm::sys::path::convert_to_slash(Dir); + // We need the native slashes for the actual file system interactions. + SmallString<128> NativeRelDir = StringRef(RelDir); + llvm::sys::path::native(NativeRelDir); + auto FS = getSourceManager().getFileManager().getVirtualFileSystem(); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo(), + CodeCompletionContext::CCC_IncludedFile); + llvm::DenseSet<StringRef> SeenResults; // To deduplicate results. + + // Helper: adds one file or directory completion result. + auto AddCompletion = [&](StringRef Filename, bool IsDirectory) { + SmallString<64> TypedChunk = Filename; + // Directory completion is up to the slash, e.g. <sys/ + TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"'); + auto R = SeenResults.insert(TypedChunk); + if (R.second) { // New completion + const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk); + *R.first = InternedTyped; // Avoid dangling StringRef. + CodeCompletionBuilder Builder(CodeCompleter->getAllocator(), + CodeCompleter->getCodeCompletionTUInfo()); + Builder.AddTypedTextChunk(InternedTyped); + // The result is a "Pattern", which is pretty opaque. + // We may want to include the real filename to allow smart ranking. + Results.AddResult(CodeCompletionResult(Builder.TakeString())); + } + }; + + // Helper: scans IncludeDir for nice files, and adds results for each. + auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) { + llvm::SmallString<128> Dir = IncludeDir; + if (!NativeRelDir.empty()) + llvm::sys::path::append(Dir, NativeRelDir); + + std::error_code EC; + unsigned Count = 0; + for (auto It = FS->dir_begin(Dir, EC); + !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) { + if (++Count == 2500) // If we happen to hit a huge directory, + break; // bail out early so we're not too slow. + StringRef Filename = llvm::sys::path::filename(It->path()); + switch (It->type()) { + case llvm::sys::fs::file_type::directory_file: + AddCompletion(Filename, /*IsDirectory=*/true); + break; + case llvm::sys::fs::file_type::regular_file: + // Only files that really look like headers. (Except in system dirs). + if (!IsSystem) { + // Header extensions from Types.def, which we can't depend on here. + if (!(Filename.endswith_lower(".h") || + Filename.endswith_lower(".hh") || + Filename.endswith_lower(".hpp") || + Filename.endswith_lower(".inc"))) + break; + } + AddCompletion(Filename, /*IsDirectory=*/false); + break; + default: + break; + } + } + }; + + // Helper: adds results relative to IncludeDir, if possible. + auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir, + bool IsSystem) { + switch (IncludeDir.getLookupType()) { + case DirectoryLookup::LT_HeaderMap: + // header maps are not (currently) enumerable. + break; + case DirectoryLookup::LT_NormalDir: + AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem); + break; + case DirectoryLookup::LT_Framework: + AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem); + break; + } + }; + + // Finally with all our helpers, we can scan the include path. + // Do this in standard order so deduplication keeps the right file. + // (In case we decide to add more details to the results later). + const auto &S = PP.getHeaderSearchInfo(); + using llvm::make_range; + if (!Angled) { + // The current directory is on the include path for "quoted" includes. + auto *CurFile = PP.getCurrentFileLexer()->getFileEntry(); + if (CurFile && CurFile->getDir()) + AddFilesFromIncludeDir(CurFile->getDir()->getName(), false); + for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end())) + AddFilesFromDirLookup(D, false); + } + for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end())) + AddFilesFromDirLookup(D, false); + for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end())) + AddFilesFromDirLookup(D, true); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + void Sema::CodeCompleteNaturalLanguage() { HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_NaturalLanguage, - nullptr, 0); + CodeCompletionContext::CCC_NaturalLanguage, nullptr, + 0); } void Sema::CodeCompleteAvailabilityPlatformName() { @@ -8006,9 +8378,9 @@ void Sema::CodeCompleteAvailabilityPlatformName() { Results.data(), Results.size()); } -void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - SmallVectorImpl<CodeCompletionResult> &Results) { +void Sema::GatherGlobalCodeCompletions( + CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, + SmallVectorImpl<CodeCompletionResult> &Results) { ResultBuilder Builder(*this, Allocator, CCTUInfo, CodeCompletionContext::CCC_Recovery); if (!CodeCompleter || CodeCompleter->includeGlobals()) { @@ -8020,9 +8392,11 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, } if (!CodeCompleter || CodeCompleter->includeMacros()) - AddMacroResults(PP, Builder, true); + AddMacroResults(PP, Builder, + CodeCompleter ? CodeCompleter->loadExternal() : false, + true); Results.clear(); - Results.insert(Results.end(), - Builder.data(), Builder.data() + Builder.size()); + Results.insert(Results.end(), Builder.data(), + Builder.data() + Builder.size()); } |