Path: blob/main/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
35233 views
//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the code-completion semantic actions.9//10//===----------------------------------------------------------------------===//11#include "clang/AST/ASTConcept.h"12#include "clang/AST/Decl.h"13#include "clang/AST/DeclBase.h"14#include "clang/AST/DeclCXX.h"15#include "clang/AST/DeclObjC.h"16#include "clang/AST/DeclTemplate.h"17#include "clang/AST/Expr.h"18#include "clang/AST/ExprCXX.h"19#include "clang/AST/ExprConcepts.h"20#include "clang/AST/ExprObjC.h"21#include "clang/AST/NestedNameSpecifier.h"22#include "clang/AST/OperationKinds.h"23#include "clang/AST/QualTypeNames.h"24#include "clang/AST/RecursiveASTVisitor.h"25#include "clang/AST/Type.h"26#include "clang/Basic/AttributeCommonInfo.h"27#include "clang/Basic/CharInfo.h"28#include "clang/Basic/OperatorKinds.h"29#include "clang/Basic/Specifiers.h"30#include "clang/Lex/HeaderSearch.h"31#include "clang/Lex/MacroInfo.h"32#include "clang/Lex/Preprocessor.h"33#include "clang/Sema/CodeCompleteConsumer.h"34#include "clang/Sema/DeclSpec.h"35#include "clang/Sema/Designator.h"36#include "clang/Sema/Lookup.h"37#include "clang/Sema/Overload.h"38#include "clang/Sema/ParsedAttr.h"39#include "clang/Sema/ParsedTemplate.h"40#include "clang/Sema/Scope.h"41#include "clang/Sema/ScopeInfo.h"42#include "clang/Sema/Sema.h"43#include "clang/Sema/SemaCodeCompletion.h"44#include "clang/Sema/SemaInternal.h"45#include "clang/Sema/SemaObjC.h"46#include "llvm/ADT/ArrayRef.h"47#include "llvm/ADT/DenseSet.h"48#include "llvm/ADT/SmallBitVector.h"49#include "llvm/ADT/SmallPtrSet.h"50#include "llvm/ADT/SmallString.h"51#include "llvm/ADT/StringExtras.h"52#include "llvm/ADT/StringSwitch.h"53#include "llvm/ADT/Twine.h"54#include "llvm/ADT/iterator_range.h"55#include "llvm/Support/Casting.h"56#include "llvm/Support/Path.h"57#include "llvm/Support/raw_ostream.h"5859#include <list>60#include <map>61#include <optional>62#include <string>63#include <vector>6465using namespace clang;66using namespace sema;6768namespace {69/// A container of code-completion results.70class ResultBuilder {71public:72/// The type of a name-lookup filter, which can be provided to the73/// name-lookup routines to specify which declarations should be included in74/// the result set (when it returns true) and which declarations should be75/// filtered out (returns false).76typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;7778typedef CodeCompletionResult Result;7980private:81/// The actual results we have found.82std::vector<Result> Results;8384/// A record of all of the declarations we have found and placed85/// into the result set, used to ensure that no declaration ever gets into86/// the result set twice.87llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;8889typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;9091/// An entry in the shadow map, which is optimized to store92/// a single (declaration, index) mapping (the common case) but93/// can also store a list of (declaration, index) mappings.94class ShadowMapEntry {95typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;9697/// Contains either the solitary NamedDecl * or a vector98/// of (declaration, index) pairs.99llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;100101/// When the entry contains a single declaration, this is102/// the index associated with that entry.103unsigned SingleDeclIndex = 0;104105public:106ShadowMapEntry() = default;107ShadowMapEntry(const ShadowMapEntry &) = delete;108ShadowMapEntry(ShadowMapEntry &&Move) { *this = std::move(Move); }109ShadowMapEntry &operator=(const ShadowMapEntry &) = delete;110ShadowMapEntry &operator=(ShadowMapEntry &&Move) {111SingleDeclIndex = Move.SingleDeclIndex;112DeclOrVector = Move.DeclOrVector;113Move.DeclOrVector = nullptr;114return *this;115}116117void Add(const NamedDecl *ND, unsigned Index) {118if (DeclOrVector.isNull()) {119// 0 - > 1 elements: just set the single element information.120DeclOrVector = ND;121SingleDeclIndex = Index;122return;123}124125if (const NamedDecl *PrevND =126DeclOrVector.dyn_cast<const NamedDecl *>()) {127// 1 -> 2 elements: create the vector of results and push in the128// existing declaration.129DeclIndexPairVector *Vec = new DeclIndexPairVector;130Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));131DeclOrVector = Vec;132}133134// Add the new element to the end of the vector.135DeclOrVector.get<DeclIndexPairVector *>()->push_back(136DeclIndexPair(ND, Index));137}138139~ShadowMapEntry() {140if (DeclIndexPairVector *Vec =141DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {142delete Vec;143DeclOrVector = ((NamedDecl *)nullptr);144}145}146147// Iteration.148class iterator;149iterator begin() const;150iterator end() const;151};152153/// A mapping from declaration names to the declarations that have154/// this name within a particular scope and their index within the list of155/// results.156typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;157158/// The semantic analysis object for which results are being159/// produced.160Sema &SemaRef;161162/// The allocator used to allocate new code-completion strings.163CodeCompletionAllocator &Allocator;164165CodeCompletionTUInfo &CCTUInfo;166167/// If non-NULL, a filter function used to remove any code-completion168/// results that are not desirable.169LookupFilter Filter;170171/// Whether we should allow declarations as172/// nested-name-specifiers that would otherwise be filtered out.173bool AllowNestedNameSpecifiers;174175/// If set, the type that we would prefer our resulting value176/// declarations to have.177///178/// Closely matching the preferred type gives a boost to a result's179/// priority.180CanQualType PreferredType;181182/// A list of shadow maps, which is used to model name hiding at183/// different levels of, e.g., the inheritance hierarchy.184std::list<ShadowMap> ShadowMaps;185186/// Overloaded C++ member functions found by SemaLookup.187/// Used to determine when one overload is dominated by another.188llvm::DenseMap<std::pair<DeclContext *, /*Name*/uintptr_t>, ShadowMapEntry>189OverloadMap;190191/// If we're potentially referring to a C++ member function, the set192/// of qualifiers applied to the object type.193Qualifiers ObjectTypeQualifiers;194/// The kind of the object expression, for rvalue/lvalue overloads.195ExprValueKind ObjectKind;196197/// Whether the \p ObjectTypeQualifiers field is active.198bool HasObjectTypeQualifiers;199200/// The selector that we prefer.201Selector PreferredSelector;202203/// The completion context in which we are gathering results.204CodeCompletionContext CompletionContext;205206/// If we are in an instance method definition, the \@implementation207/// object.208ObjCImplementationDecl *ObjCImplementation;209210void AdjustResultPriorityForDecl(Result &R);211212void MaybeAddConstructorResults(Result R);213214public:215explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,216CodeCompletionTUInfo &CCTUInfo,217const CodeCompletionContext &CompletionContext,218LookupFilter Filter = nullptr)219: SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),220Filter(Filter), AllowNestedNameSpecifiers(false),221HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),222ObjCImplementation(nullptr) {223// If this is an Objective-C instance method definition, dig out the224// corresponding implementation.225switch (CompletionContext.getKind()) {226case CodeCompletionContext::CCC_Expression:227case CodeCompletionContext::CCC_ObjCMessageReceiver:228case CodeCompletionContext::CCC_ParenthesizedExpression:229case CodeCompletionContext::CCC_Statement:230case CodeCompletionContext::CCC_TopLevelOrExpression:231case CodeCompletionContext::CCC_Recovery:232if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())233if (Method->isInstanceMethod())234if (ObjCInterfaceDecl *Interface = Method->getClassInterface())235ObjCImplementation = Interface->getImplementation();236break;237238default:239break;240}241}242243/// Determine the priority for a reference to the given declaration.244unsigned getBasePriority(const NamedDecl *D);245246/// Whether we should include code patterns in the completion247/// results.248bool includeCodePatterns() const {249return SemaRef.CodeCompletion().CodeCompleter &&250SemaRef.CodeCompletion().CodeCompleter->includeCodePatterns();251}252253/// Set the filter used for code-completion results.254void setFilter(LookupFilter Filter) { this->Filter = Filter; }255256Result *data() { return Results.empty() ? nullptr : &Results.front(); }257unsigned size() const { return Results.size(); }258bool empty() const { return Results.empty(); }259260/// Specify the preferred type.261void setPreferredType(QualType T) {262PreferredType = SemaRef.Context.getCanonicalType(T);263}264265/// Set the cv-qualifiers on the object type, for us in filtering266/// calls to member functions.267///268/// When there are qualifiers in this set, they will be used to filter269/// out member functions that aren't available (because there will be a270/// cv-qualifier mismatch) or prefer functions with an exact qualifier271/// match.272void setObjectTypeQualifiers(Qualifiers Quals, ExprValueKind Kind) {273ObjectTypeQualifiers = Quals;274ObjectKind = Kind;275HasObjectTypeQualifiers = true;276}277278/// Set the preferred selector.279///280/// When an Objective-C method declaration result is added, and that281/// method's selector matches this preferred selector, we give that method282/// a slight priority boost.283void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }284285/// Retrieve the code-completion context for which results are286/// being collected.287const CodeCompletionContext &getCompletionContext() const {288return CompletionContext;289}290291/// Specify whether nested-name-specifiers are allowed.292void allowNestedNameSpecifiers(bool Allow = true) {293AllowNestedNameSpecifiers = Allow;294}295296/// Return the semantic analysis object for which we are collecting297/// code completion results.298Sema &getSema() const { return SemaRef; }299300/// Retrieve the allocator used to allocate code completion strings.301CodeCompletionAllocator &getAllocator() const { return Allocator; }302303CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }304305/// Determine whether the given declaration is at all interesting306/// as a code-completion result.307///308/// \param ND the declaration that we are inspecting.309///310/// \param AsNestedNameSpecifier will be set true if this declaration is311/// only interesting when it is a nested-name-specifier.312bool isInterestingDecl(const NamedDecl *ND,313bool &AsNestedNameSpecifier) const;314315/// Decide whether or not a use of function Decl can be a call.316///317/// \param ND the function declaration.318///319/// \param BaseExprType the object type in a member access expression,320/// if any.321bool canFunctionBeCalled(const NamedDecl *ND, QualType BaseExprType) const;322323/// Decide whether or not a use of member function Decl can be a call.324///325/// \param Method the function declaration.326///327/// \param BaseExprType the object type in a member access expression,328/// if any.329bool canCxxMethodBeCalled(const CXXMethodDecl *Method,330QualType BaseExprType) const;331332/// Check whether the result is hidden by the Hiding declaration.333///334/// \returns true if the result is hidden and cannot be found, false if335/// the hidden result could still be found. When false, \p R may be336/// modified to describe how the result can be found (e.g., via extra337/// qualification).338bool CheckHiddenResult(Result &R, DeclContext *CurContext,339const NamedDecl *Hiding);340341/// Add a new result to this result set (if it isn't already in one342/// of the shadow maps), or replace an existing result (for, e.g., a343/// redeclaration).344///345/// \param R the result to add (if it is unique).346///347/// \param CurContext the context in which this result will be named.348void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);349350/// Add a new result to this result set, where we already know351/// the hiding declaration (if any).352///353/// \param R the result to add (if it is unique).354///355/// \param CurContext the context in which this result will be named.356///357/// \param Hiding the declaration that hides the result.358///359/// \param InBaseClass whether the result was found in a base360/// class of the searched context.361///362/// \param BaseExprType the type of expression that precedes the "." or "->"363/// in a member access expression.364void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,365bool InBaseClass, QualType BaseExprType);366367/// Add a new non-declaration result to this result set.368void AddResult(Result R);369370/// Enter into a new scope.371void EnterNewScope();372373/// Exit from the current scope.374void ExitScope();375376/// Ignore this declaration, if it is seen again.377void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }378379/// Add a visited context.380void addVisitedContext(DeclContext *Ctx) {381CompletionContext.addVisitedContext(Ctx);382}383384/// \name Name lookup predicates385///386/// These predicates can be passed to the name lookup functions to filter the387/// results of name lookup. All of the predicates have the same type, so that388///389//@{390bool IsOrdinaryName(const NamedDecl *ND) const;391bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;392bool IsIntegralConstantValue(const NamedDecl *ND) const;393bool IsOrdinaryNonValueName(const NamedDecl *ND) const;394bool IsNestedNameSpecifier(const NamedDecl *ND) const;395bool IsEnum(const NamedDecl *ND) const;396bool IsClassOrStruct(const NamedDecl *ND) const;397bool IsUnion(const NamedDecl *ND) const;398bool IsNamespace(const NamedDecl *ND) const;399bool IsNamespaceOrAlias(const NamedDecl *ND) const;400bool IsType(const NamedDecl *ND) const;401bool IsMember(const NamedDecl *ND) const;402bool IsObjCIvar(const NamedDecl *ND) const;403bool IsObjCMessageReceiver(const NamedDecl *ND) const;404bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;405bool IsObjCCollection(const NamedDecl *ND) const;406bool IsImpossibleToSatisfy(const NamedDecl *ND) const;407//@}408};409} // namespace410411void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {412if (!Enabled)413return;414if (isa<BlockDecl>(S.CurContext)) {415if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {416ComputeType = nullptr;417Type = BSI->ReturnType;418ExpectedLoc = Tok;419}420} else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) {421ComputeType = nullptr;422Type = Function->getReturnType();423ExpectedLoc = Tok;424} else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) {425ComputeType = nullptr;426Type = Method->getReturnType();427ExpectedLoc = Tok;428}429}430431void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {432if (!Enabled)433return;434auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);435ComputeType = nullptr;436Type = VD ? VD->getType() : QualType();437ExpectedLoc = Tok;438}439440static QualType getDesignatedType(QualType BaseType, const Designation &Desig);441442void PreferredTypeBuilder::enterDesignatedInitializer(SourceLocation Tok,443QualType BaseType,444const Designation &D) {445if (!Enabled)446return;447ComputeType = nullptr;448Type = getDesignatedType(BaseType, D);449ExpectedLoc = Tok;450}451452void PreferredTypeBuilder::enterFunctionArgument(453SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) {454if (!Enabled)455return;456this->ComputeType = ComputeType;457Type = QualType();458ExpectedLoc = Tok;459}460461void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,462SourceLocation LParLoc) {463if (!Enabled)464return;465// expected type for parenthesized expression does not change.466if (ExpectedLoc == LParLoc)467ExpectedLoc = Tok;468}469470static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,471tok::TokenKind Op) {472if (!LHS)473return QualType();474475QualType LHSType = LHS->getType();476if (LHSType->isPointerType()) {477if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)478return S.getASTContext().getPointerDiffType();479// Pointer difference is more common than subtracting an int from a pointer.480if (Op == tok::minus)481return LHSType;482}483484switch (Op) {485// No way to infer the type of RHS from LHS.486case tok::comma:487return QualType();488// Prefer the type of the left operand for all of these.489// Arithmetic operations.490case tok::plus:491case tok::plusequal:492case tok::minus:493case tok::minusequal:494case tok::percent:495case tok::percentequal:496case tok::slash:497case tok::slashequal:498case tok::star:499case tok::starequal:500// Assignment.501case tok::equal:502// Comparison operators.503case tok::equalequal:504case tok::exclaimequal:505case tok::less:506case tok::lessequal:507case tok::greater:508case tok::greaterequal:509case tok::spaceship:510return LHS->getType();511// Binary shifts are often overloaded, so don't try to guess those.512case tok::greatergreater:513case tok::greatergreaterequal:514case tok::lessless:515case tok::lesslessequal:516if (LHSType->isIntegralOrEnumerationType())517return S.getASTContext().IntTy;518return QualType();519// Logical operators, assume we want bool.520case tok::ampamp:521case tok::pipepipe:522case tok::caretcaret:523return S.getASTContext().BoolTy;524// Operators often used for bit manipulation are typically used with the type525// of the left argument.526case tok::pipe:527case tok::pipeequal:528case tok::caret:529case tok::caretequal:530case tok::amp:531case tok::ampequal:532if (LHSType->isIntegralOrEnumerationType())533return LHSType;534return QualType();535// RHS should be a pointer to a member of the 'LHS' type, but we can't give536// any particular type here.537case tok::periodstar:538case tok::arrowstar:539return QualType();540default:541// FIXME(ibiryukov): handle the missing op, re-add the assertion.542// assert(false && "unhandled binary op");543return QualType();544}545}546547/// Get preferred type for an argument of an unary expression. \p ContextType is548/// preferred type of the whole unary expression.549static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType,550tok::TokenKind Op) {551switch (Op) {552case tok::exclaim:553return S.getASTContext().BoolTy;554case tok::amp:555if (!ContextType.isNull() && ContextType->isPointerType())556return ContextType->getPointeeType();557return QualType();558case tok::star:559if (ContextType.isNull())560return QualType();561return S.getASTContext().getPointerType(ContextType.getNonReferenceType());562case tok::plus:563case tok::minus:564case tok::tilde:565case tok::minusminus:566case tok::plusplus:567if (ContextType.isNull())568return S.getASTContext().IntTy;569// leave as is, these operators typically return the same type.570return ContextType;571case tok::kw___real:572case tok::kw___imag:573return QualType();574default:575assert(false && "unhandled unary op");576return QualType();577}578}579580void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,581tok::TokenKind Op) {582if (!Enabled)583return;584ComputeType = nullptr;585Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);586ExpectedLoc = Tok;587}588589void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok,590Expr *Base) {591if (!Enabled || !Base)592return;593// Do we have expected type for Base?594if (ExpectedLoc != Base->getBeginLoc())595return;596// Keep the expected type, only update the location.597ExpectedLoc = Tok;598}599600void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,601tok::TokenKind OpKind,602SourceLocation OpLoc) {603if (!Enabled)604return;605ComputeType = nullptr;606Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);607ExpectedLoc = Tok;608}609610void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,611Expr *LHS) {612if (!Enabled)613return;614ComputeType = nullptr;615Type = S.getASTContext().IntTy;616ExpectedLoc = Tok;617}618619void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,620QualType CastType) {621if (!Enabled)622return;623ComputeType = nullptr;624Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();625ExpectedLoc = Tok;626}627628void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {629if (!Enabled)630return;631ComputeType = nullptr;632Type = S.getASTContext().BoolTy;633ExpectedLoc = Tok;634}635636class ResultBuilder::ShadowMapEntry::iterator {637llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;638unsigned SingleDeclIndex;639640public:641typedef DeclIndexPair value_type;642typedef value_type reference;643typedef std::ptrdiff_t difference_type;644typedef std::input_iterator_tag iterator_category;645646class pointer {647DeclIndexPair Value;648649public:650pointer(const DeclIndexPair &Value) : Value(Value) {}651652const DeclIndexPair *operator->() const { return &Value; }653};654655iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}656657iterator(const NamedDecl *SingleDecl, unsigned Index)658: DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}659660iterator(const DeclIndexPair *Iterator)661: DeclOrIterator(Iterator), SingleDeclIndex(0) {}662663iterator &operator++() {664if (DeclOrIterator.is<const NamedDecl *>()) {665DeclOrIterator = (NamedDecl *)nullptr;666SingleDeclIndex = 0;667return *this;668}669670const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();671++I;672DeclOrIterator = I;673return *this;674}675676/*iterator operator++(int) {677iterator tmp(*this);678++(*this);679return tmp;680}*/681682reference operator*() const {683if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())684return reference(ND, SingleDeclIndex);685686return *DeclOrIterator.get<const DeclIndexPair *>();687}688689pointer operator->() const { return pointer(**this); }690691friend bool operator==(const iterator &X, const iterator &Y) {692return X.DeclOrIterator.getOpaqueValue() ==693Y.DeclOrIterator.getOpaqueValue() &&694X.SingleDeclIndex == Y.SingleDeclIndex;695}696697friend bool operator!=(const iterator &X, const iterator &Y) {698return !(X == Y);699}700};701702ResultBuilder::ShadowMapEntry::iterator703ResultBuilder::ShadowMapEntry::begin() const {704if (DeclOrVector.isNull())705return iterator();706707if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())708return iterator(ND, SingleDeclIndex);709710return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());711}712713ResultBuilder::ShadowMapEntry::iterator714ResultBuilder::ShadowMapEntry::end() const {715if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())716return iterator();717718return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());719}720721/// Compute the qualification required to get from the current context722/// (\p CurContext) to the target context (\p TargetContext).723///724/// \param Context the AST context in which the qualification will be used.725///726/// \param CurContext the context where an entity is being named, which is727/// typically based on the current scope.728///729/// \param TargetContext the context in which the named entity actually730/// resides.731///732/// \returns a nested name specifier that refers into the target context, or733/// NULL if no qualification is needed.734static NestedNameSpecifier *735getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,736const DeclContext *TargetContext) {737SmallVector<const DeclContext *, 4> TargetParents;738739for (const DeclContext *CommonAncestor = TargetContext;740CommonAncestor && !CommonAncestor->Encloses(CurContext);741CommonAncestor = CommonAncestor->getLookupParent()) {742if (CommonAncestor->isTransparentContext() ||743CommonAncestor->isFunctionOrMethod())744continue;745746TargetParents.push_back(CommonAncestor);747}748749NestedNameSpecifier *Result = nullptr;750while (!TargetParents.empty()) {751const DeclContext *Parent = TargetParents.pop_back_val();752753if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {754if (!Namespace->getIdentifier())755continue;756757Result = NestedNameSpecifier::Create(Context, Result, Namespace);758} else if (const auto *TD = dyn_cast<TagDecl>(Parent))759Result = NestedNameSpecifier::Create(760Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());761}762return Result;763}764765// Some declarations have reserved names that we don't want to ever show.766// Filter out names reserved for the implementation if they come from a767// system header.768static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {769// Debuggers want access to all identifiers, including reserved ones.770if (SemaRef.getLangOpts().DebuggerSupport)771return false;772773ReservedIdentifierStatus Status = ND->isReserved(SemaRef.getLangOpts());774// Ignore reserved names for compiler provided decls.775if (isReservedInAllContexts(Status) && ND->getLocation().isInvalid())776return true;777778// For system headers ignore only double-underscore names.779// This allows for system headers providing private symbols with a single780// underscore.781if (Status == ReservedIdentifierStatus::StartsWithDoubleUnderscore &&782SemaRef.SourceMgr.isInSystemHeader(783SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))784return true;785786return false;787}788789bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,790bool &AsNestedNameSpecifier) const {791AsNestedNameSpecifier = false;792793auto *Named = ND;794ND = ND->getUnderlyingDecl();795796// Skip unnamed entities.797if (!ND->getDeclName())798return false;799800// Friend declarations and declarations introduced due to friends are never801// added as results.802if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)803return false;804805// Class template (partial) specializations are never added as results.806if (isa<ClassTemplateSpecializationDecl>(ND) ||807isa<ClassTemplatePartialSpecializationDecl>(ND))808return false;809810// Using declarations themselves are never added as results.811if (isa<UsingDecl>(ND))812return false;813814if (shouldIgnoreDueToReservedName(ND, SemaRef))815return false;816817if (Filter == &ResultBuilder::IsNestedNameSpecifier ||818(isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&819Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))820AsNestedNameSpecifier = true;821822// Filter out any unwanted results.823if (Filter && !(this->*Filter)(Named)) {824// Check whether it is interesting as a nested-name-specifier.825if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&826IsNestedNameSpecifier(ND) &&827(Filter != &ResultBuilder::IsMember ||828(isa<CXXRecordDecl>(ND) &&829cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {830AsNestedNameSpecifier = true;831return true;832}833834return false;835}836// ... then it must be interesting!837return true;838}839840bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,841const NamedDecl *Hiding) {842// In C, there is no way to refer to a hidden name.843// FIXME: This isn't true; we can find a tag name hidden by an ordinary844// name if we introduce the tag type.845if (!SemaRef.getLangOpts().CPlusPlus)846return true;847848const DeclContext *HiddenCtx =849R.Declaration->getDeclContext()->getRedeclContext();850851// There is no way to qualify a name declared in a function or method.852if (HiddenCtx->isFunctionOrMethod())853return true;854855if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())856return true;857858// We can refer to the result with the appropriate qualification. Do it.859R.Hidden = true;860R.QualifierIsInformative = false;861862if (!R.Qualifier)863R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,864R.Declaration->getDeclContext());865return false;866}867868/// A simplified classification of types used to determine whether two869/// types are "similar enough" when adjusting priorities.870SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {871switch (T->getTypeClass()) {872case Type::Builtin:873switch (cast<BuiltinType>(T)->getKind()) {874case BuiltinType::Void:875return STC_Void;876877case BuiltinType::NullPtr:878return STC_Pointer;879880case BuiltinType::Overload:881case BuiltinType::Dependent:882return STC_Other;883884case BuiltinType::ObjCId:885case BuiltinType::ObjCClass:886case BuiltinType::ObjCSel:887return STC_ObjectiveC;888889default:890return STC_Arithmetic;891}892893case Type::Complex:894return STC_Arithmetic;895896case Type::Pointer:897return STC_Pointer;898899case Type::BlockPointer:900return STC_Block;901902case Type::LValueReference:903case Type::RValueReference:904return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());905906case Type::ConstantArray:907case Type::IncompleteArray:908case Type::VariableArray:909case Type::DependentSizedArray:910return STC_Array;911912case Type::DependentSizedExtVector:913case Type::Vector:914case Type::ExtVector:915return STC_Arithmetic;916917case Type::FunctionProto:918case Type::FunctionNoProto:919return STC_Function;920921case Type::Record:922return STC_Record;923924case Type::Enum:925return STC_Arithmetic;926927case Type::ObjCObject:928case Type::ObjCInterface:929case Type::ObjCObjectPointer:930return STC_ObjectiveC;931932default:933return STC_Other;934}935}936937/// Get the type that a given expression will have if this declaration938/// is used as an expression in its "typical" code-completion form.939QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {940ND = ND->getUnderlyingDecl();941942if (const auto *Type = dyn_cast<TypeDecl>(ND))943return C.getTypeDeclType(Type);944if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))945return C.getObjCInterfaceType(Iface);946947QualType T;948if (const FunctionDecl *Function = ND->getAsFunction())949T = Function->getCallResultType();950else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))951T = Method->getSendResultType();952else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))953T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));954else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))955T = Property->getType();956else if (const auto *Value = dyn_cast<ValueDecl>(ND))957T = Value->getType();958959if (T.isNull())960return QualType();961962// Dig through references, function pointers, and block pointers to963// get down to the likely type of an expression when the entity is964// used.965do {966if (const auto *Ref = T->getAs<ReferenceType>()) {967T = Ref->getPointeeType();968continue;969}970971if (const auto *Pointer = T->getAs<PointerType>()) {972if (Pointer->getPointeeType()->isFunctionType()) {973T = Pointer->getPointeeType();974continue;975}976977break;978}979980if (const auto *Block = T->getAs<BlockPointerType>()) {981T = Block->getPointeeType();982continue;983}984985if (const auto *Function = T->getAs<FunctionType>()) {986T = Function->getReturnType();987continue;988}989990break;991} while (true);992993return T;994}995996unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {997if (!ND)998return CCP_Unlikely;9991000// Context-based decisions.1001const DeclContext *LexicalDC = ND->getLexicalDeclContext();1002if (LexicalDC->isFunctionOrMethod()) {1003// _cmd is relatively rare1004if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))1005if (ImplicitParam->getIdentifier() &&1006ImplicitParam->getIdentifier()->isStr("_cmd"))1007return CCP_ObjC_cmd;10081009return CCP_LocalDeclaration;1010}10111012const DeclContext *DC = ND->getDeclContext()->getRedeclContext();1013if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {1014// Explicit destructor calls are very rare.1015if (isa<CXXDestructorDecl>(ND))1016return CCP_Unlikely;1017// Explicit operator and conversion function calls are also very rare.1018auto DeclNameKind = ND->getDeclName().getNameKind();1019if (DeclNameKind == DeclarationName::CXXOperatorName ||1020DeclNameKind == DeclarationName::CXXLiteralOperatorName ||1021DeclNameKind == DeclarationName::CXXConversionFunctionName)1022return CCP_Unlikely;1023return CCP_MemberDeclaration;1024}10251026// Content-based decisions.1027if (isa<EnumConstantDecl>(ND))1028return CCP_Constant;10291030// Use CCP_Type for type declarations unless we're in a statement, Objective-C1031// message receiver, or parenthesized expression context. There, it's as1032// likely that the user will want to write a type as other declarations.1033if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&1034!(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||1035CompletionContext.getKind() ==1036CodeCompletionContext::CCC_ObjCMessageReceiver ||1037CompletionContext.getKind() ==1038CodeCompletionContext::CCC_ParenthesizedExpression))1039return CCP_Type;10401041return CCP_Declaration;1042}10431044void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {1045// If this is an Objective-C method declaration whose selector matches our1046// preferred selector, give it a priority boost.1047if (!PreferredSelector.isNull())1048if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))1049if (PreferredSelector == Method->getSelector())1050R.Priority += CCD_SelectorMatch;10511052// If we have a preferred type, adjust the priority for results with exactly-1053// matching or nearly-matching types.1054if (!PreferredType.isNull()) {1055QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);1056if (!T.isNull()) {1057CanQualType TC = SemaRef.Context.getCanonicalType(T);1058// Check for exactly-matching types (modulo qualifiers).1059if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))1060R.Priority /= CCF_ExactTypeMatch;1061// Check for nearly-matching types, based on classification of each.1062else if ((getSimplifiedTypeClass(PreferredType) ==1063getSimplifiedTypeClass(TC)) &&1064!(PreferredType->isEnumeralType() && TC->isEnumeralType()))1065R.Priority /= CCF_SimilarTypeMatch;1066}1067}1068}10691070static DeclContext::lookup_result getConstructors(ASTContext &Context,1071const CXXRecordDecl *Record) {1072QualType RecordTy = Context.getTypeDeclType(Record);1073DeclarationName ConstructorName =1074Context.DeclarationNames.getCXXConstructorName(1075Context.getCanonicalType(RecordTy));1076return Record->lookup(ConstructorName);1077}10781079void ResultBuilder::MaybeAddConstructorResults(Result R) {1080if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||1081!CompletionContext.wantConstructorResults())1082return;10831084const NamedDecl *D = R.Declaration;1085const CXXRecordDecl *Record = nullptr;1086if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))1087Record = ClassTemplate->getTemplatedDecl();1088else if ((Record = dyn_cast<CXXRecordDecl>(D))) {1089// Skip specializations and partial specializations.1090if (isa<ClassTemplateSpecializationDecl>(Record))1091return;1092} else {1093// There are no constructors here.1094return;1095}10961097Record = Record->getDefinition();1098if (!Record)1099return;11001101for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {1102R.Declaration = Ctor;1103R.CursorKind = getCursorKindForDecl(R.Declaration);1104Results.push_back(R);1105}1106}11071108static bool isConstructor(const Decl *ND) {1109if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))1110ND = Tmpl->getTemplatedDecl();1111return isa<CXXConstructorDecl>(ND);1112}11131114void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {1115assert(!ShadowMaps.empty() && "Must enter into a results scope");11161117if (R.Kind != Result::RK_Declaration) {1118// For non-declaration results, just add the result.1119Results.push_back(R);1120return;1121}11221123// Look through using declarations.1124if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {1125CodeCompletionResult Result(Using->getTargetDecl(),1126getBasePriority(Using->getTargetDecl()),1127R.Qualifier, false,1128(R.Availability == CXAvailability_Available ||1129R.Availability == CXAvailability_Deprecated),1130std::move(R.FixIts));1131Result.ShadowDecl = Using;1132MaybeAddResult(Result, CurContext);1133return;1134}11351136const Decl *CanonDecl = R.Declaration->getCanonicalDecl();1137unsigned IDNS = CanonDecl->getIdentifierNamespace();11381139bool AsNestedNameSpecifier = false;1140if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))1141return;11421143// C++ constructors are never found by name lookup.1144if (isConstructor(R.Declaration))1145return;11461147ShadowMap &SMap = ShadowMaps.back();1148ShadowMapEntry::iterator I, IEnd;1149ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());1150if (NamePos != SMap.end()) {1151I = NamePos->second.begin();1152IEnd = NamePos->second.end();1153}11541155for (; I != IEnd; ++I) {1156const NamedDecl *ND = I->first;1157unsigned Index = I->second;1158if (ND->getCanonicalDecl() == CanonDecl) {1159// This is a redeclaration. Always pick the newer declaration.1160Results[Index].Declaration = R.Declaration;11611162// We're done.1163return;1164}1165}11661167// This is a new declaration in this scope. However, check whether this1168// declaration name is hidden by a similarly-named declaration in an outer1169// scope.1170std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();1171--SMEnd;1172for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {1173ShadowMapEntry::iterator I, IEnd;1174ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());1175if (NamePos != SM->end()) {1176I = NamePos->second.begin();1177IEnd = NamePos->second.end();1178}1179for (; I != IEnd; ++I) {1180// A tag declaration does not hide a non-tag declaration.1181if (I->first->hasTagIdentifierNamespace() &&1182(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |1183Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))1184continue;11851186// Protocols are in distinct namespaces from everything else.1187if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||1188(IDNS & Decl::IDNS_ObjCProtocol)) &&1189I->first->getIdentifierNamespace() != IDNS)1190continue;11911192// The newly-added result is hidden by an entry in the shadow map.1193if (CheckHiddenResult(R, CurContext, I->first))1194return;11951196break;1197}1198}11991200// Make sure that any given declaration only shows up in the result set once.1201if (!AllDeclsFound.insert(CanonDecl).second)1202return;12031204// If the filter is for nested-name-specifiers, then this result starts a1205// nested-name-specifier.1206if (AsNestedNameSpecifier) {1207R.StartsNestedNameSpecifier = true;1208R.Priority = CCP_NestedNameSpecifier;1209} else1210AdjustResultPriorityForDecl(R);12111212// If this result is supposed to have an informative qualifier, add one.1213if (R.QualifierIsInformative && !R.Qualifier &&1214!R.StartsNestedNameSpecifier) {1215const DeclContext *Ctx = R.Declaration->getDeclContext();1216if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))1217R.Qualifier =1218NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);1219else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))1220R.Qualifier = NestedNameSpecifier::Create(1221SemaRef.Context, nullptr, false,1222SemaRef.Context.getTypeDeclType(Tag).getTypePtr());1223else1224R.QualifierIsInformative = false;1225}12261227// Insert this result into the set of results and into the current shadow1228// map.1229SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());1230Results.push_back(R);12311232if (!AsNestedNameSpecifier)1233MaybeAddConstructorResults(R);1234}12351236static void setInBaseClass(ResultBuilder::Result &R) {1237R.Priority += CCD_InBaseClass;1238R.InBaseClass = true;1239}12401241enum class OverloadCompare { BothViable, Dominates, Dominated };1242// Will Candidate ever be called on the object, when overloaded with Incumbent?1243// Returns Dominates if Candidate is always called, Dominated if Incumbent is1244// always called, BothViable if either may be called depending on arguments.1245// Precondition: must actually be overloads!1246static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate,1247const CXXMethodDecl &Incumbent,1248const Qualifiers &ObjectQuals,1249ExprValueKind ObjectKind) {1250// Base/derived shadowing is handled elsewhere.1251if (Candidate.getDeclContext() != Incumbent.getDeclContext())1252return OverloadCompare::BothViable;1253if (Candidate.isVariadic() != Incumbent.isVariadic() ||1254Candidate.getNumParams() != Incumbent.getNumParams() ||1255Candidate.getMinRequiredArguments() !=1256Incumbent.getMinRequiredArguments())1257return OverloadCompare::BothViable;1258for (unsigned I = 0, E = Candidate.getNumParams(); I != E; ++I)1259if (Candidate.parameters()[I]->getType().getCanonicalType() !=1260Incumbent.parameters()[I]->getType().getCanonicalType())1261return OverloadCompare::BothViable;1262if (!Candidate.specific_attrs<EnableIfAttr>().empty() ||1263!Incumbent.specific_attrs<EnableIfAttr>().empty())1264return OverloadCompare::BothViable;1265// At this point, we know calls can't pick one or the other based on1266// arguments, so one of the two must win. (Or both fail, handled elsewhere).1267RefQualifierKind CandidateRef = Candidate.getRefQualifier();1268RefQualifierKind IncumbentRef = Incumbent.getRefQualifier();1269if (CandidateRef != IncumbentRef) {1270// If the object kind is LValue/RValue, there's one acceptable ref-qualifier1271// and it can't be mixed with ref-unqualified overloads (in valid code).12721273// For xvalue objects, we prefer the rvalue overload even if we have to1274// add qualifiers (which is rare, because const&& is rare).1275if (ObjectKind == clang::VK_XValue)1276return CandidateRef == RQ_RValue ? OverloadCompare::Dominates1277: OverloadCompare::Dominated;1278}1279// Now the ref qualifiers are the same (or we're in some invalid state).1280// So make some decision based on the qualifiers.1281Qualifiers CandidateQual = Candidate.getMethodQualifiers();1282Qualifiers IncumbentQual = Incumbent.getMethodQualifiers();1283bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual);1284bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual);1285if (CandidateSuperset == IncumbentSuperset)1286return OverloadCompare::BothViable;1287return IncumbentSuperset ? OverloadCompare::Dominates1288: OverloadCompare::Dominated;1289}12901291bool ResultBuilder::canCxxMethodBeCalled(const CXXMethodDecl *Method,1292QualType BaseExprType) const {1293// Find the class scope that we're currently in.1294// We could e.g. be inside a lambda, so walk up the DeclContext until we1295// find a CXXMethodDecl.1296DeclContext *CurContext = SemaRef.CurContext;1297const auto *CurrentClassScope = [&]() -> const CXXRecordDecl * {1298for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getParent()) {1299const auto *CtxMethod = llvm::dyn_cast<CXXMethodDecl>(Ctx);1300if (CtxMethod && !CtxMethod->getParent()->isLambda()) {1301return CtxMethod->getParent();1302}1303}1304return nullptr;1305}();13061307// If we're not inside the scope of the method's class, it can't be a call.1308bool FunctionCanBeCall =1309CurrentClassScope &&1310(CurrentClassScope == Method->getParent() ||1311CurrentClassScope->isDerivedFrom(Method->getParent()));13121313// We skip the following calculation for exceptions if it's already true.1314if (FunctionCanBeCall)1315return true;13161317// Exception: foo->FooBase::bar() or foo->Foo::bar() *is* a call.1318if (const CXXRecordDecl *MaybeDerived =1319BaseExprType.isNull() ? nullptr1320: BaseExprType->getAsCXXRecordDecl()) {1321auto *MaybeBase = Method->getParent();1322FunctionCanBeCall =1323MaybeDerived == MaybeBase || MaybeDerived->isDerivedFrom(MaybeBase);1324}13251326return FunctionCanBeCall;1327}13281329bool ResultBuilder::canFunctionBeCalled(const NamedDecl *ND,1330QualType BaseExprType) const {1331// We apply heuristics only to CCC_Symbol:1332// * CCC_{Arrow,Dot}MemberAccess reflect member access expressions:1333// f.method() and f->method(). These are always calls.1334// * A qualified name to a member function may *not* be a call. We have to1335// subdivide the cases: For example, f.Base::method(), which is regarded as1336// CCC_Symbol, should be a call.1337// * Non-member functions and static member functions are always considered1338// calls.1339if (CompletionContext.getKind() == clang::CodeCompletionContext::CCC_Symbol) {1340if (const auto *FuncTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {1341ND = FuncTmpl->getTemplatedDecl();1342}1343const auto *Method = dyn_cast<CXXMethodDecl>(ND);1344if (Method && !Method->isStatic()) {1345return canCxxMethodBeCalled(Method, BaseExprType);1346}1347}1348return true;1349}13501351void ResultBuilder::AddResult(Result R, DeclContext *CurContext,1352NamedDecl *Hiding, bool InBaseClass = false,1353QualType BaseExprType = QualType()) {1354if (R.Kind != Result::RK_Declaration) {1355// For non-declaration results, just add the result.1356Results.push_back(R);1357return;1358}13591360// Look through using declarations.1361if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {1362CodeCompletionResult Result(Using->getTargetDecl(),1363getBasePriority(Using->getTargetDecl()),1364R.Qualifier, false,1365(R.Availability == CXAvailability_Available ||1366R.Availability == CXAvailability_Deprecated),1367std::move(R.FixIts));1368Result.ShadowDecl = Using;1369AddResult(Result, CurContext, Hiding, /*InBaseClass=*/false,1370/*BaseExprType=*/BaseExprType);1371return;1372}13731374bool AsNestedNameSpecifier = false;1375if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))1376return;13771378// C++ constructors are never found by name lookup.1379if (isConstructor(R.Declaration))1380return;13811382if (Hiding && CheckHiddenResult(R, CurContext, Hiding))1383return;13841385// Make sure that any given declaration only shows up in the result set once.1386if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)1387return;13881389// If the filter is for nested-name-specifiers, then this result starts a1390// nested-name-specifier.1391if (AsNestedNameSpecifier) {1392R.StartsNestedNameSpecifier = true;1393R.Priority = CCP_NestedNameSpecifier;1394} else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&1395InBaseClass &&1396isa<CXXRecordDecl>(1397R.Declaration->getDeclContext()->getRedeclContext()))1398R.QualifierIsInformative = true;13991400// If this result is supposed to have an informative qualifier, add one.1401if (R.QualifierIsInformative && !R.Qualifier &&1402!R.StartsNestedNameSpecifier) {1403const DeclContext *Ctx = R.Declaration->getDeclContext();1404if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))1405R.Qualifier =1406NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);1407else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))1408R.Qualifier = NestedNameSpecifier::Create(1409SemaRef.Context, nullptr, false,1410SemaRef.Context.getTypeDeclType(Tag).getTypePtr());1411else1412R.QualifierIsInformative = false;1413}14141415// Adjust the priority if this result comes from a base class.1416if (InBaseClass)1417setInBaseClass(R);14181419AdjustResultPriorityForDecl(R);14201421if (HasObjectTypeQualifiers)1422if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))1423if (Method->isInstance()) {1424Qualifiers MethodQuals = Method->getMethodQualifiers();1425if (ObjectTypeQualifiers == MethodQuals)1426R.Priority += CCD_ObjectQualifierMatch;1427else if (ObjectTypeQualifiers - MethodQuals) {1428// The method cannot be invoked, because doing so would drop1429// qualifiers.1430return;1431}1432// Detect cases where a ref-qualified method cannot be invoked.1433switch (Method->getRefQualifier()) {1434case RQ_LValue:1435if (ObjectKind != VK_LValue && !MethodQuals.hasConst())1436return;1437break;1438case RQ_RValue:1439if (ObjectKind == VK_LValue)1440return;1441break;1442case RQ_None:1443break;1444}14451446/// Check whether this dominates another overloaded method, which should1447/// be suppressed (or vice versa).1448/// Motivating case is const_iterator begin() const vs iterator begin().1449auto &OverloadSet = OverloadMap[std::make_pair(1450CurContext, Method->getDeclName().getAsOpaqueInteger())];1451for (const DeclIndexPair Entry : OverloadSet) {1452Result &Incumbent = Results[Entry.second];1453switch (compareOverloads(*Method,1454*cast<CXXMethodDecl>(Incumbent.Declaration),1455ObjectTypeQualifiers, ObjectKind)) {1456case OverloadCompare::Dominates:1457// Replace the dominated overload with this one.1458// FIXME: if the overload dominates multiple incumbents then we1459// should remove all. But two overloads is by far the common case.1460Incumbent = std::move(R);1461return;1462case OverloadCompare::Dominated:1463// This overload can't be called, drop it.1464return;1465case OverloadCompare::BothViable:1466break;1467}1468}1469OverloadSet.Add(Method, Results.size());1470}14711472R.FunctionCanBeCall = canFunctionBeCalled(R.getDeclaration(), BaseExprType);14731474// Insert this result into the set of results.1475Results.push_back(R);14761477if (!AsNestedNameSpecifier)1478MaybeAddConstructorResults(R);1479}14801481void ResultBuilder::AddResult(Result R) {1482assert(R.Kind != Result::RK_Declaration &&1483"Declaration results need more context");1484Results.push_back(R);1485}14861487/// Enter into a new scope.1488void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }14891490/// Exit from the current scope.1491void ResultBuilder::ExitScope() {1492ShadowMaps.pop_back();1493}14941495/// Determines whether this given declaration will be found by1496/// ordinary name lookup.1497bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {1498ND = ND->getUnderlyingDecl();14991500// If name lookup finds a local extern declaration, then we are in a1501// context where it behaves like an ordinary name.1502unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;1503if (SemaRef.getLangOpts().CPlusPlus)1504IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;1505else if (SemaRef.getLangOpts().ObjC) {1506if (isa<ObjCIvarDecl>(ND))1507return true;1508}15091510return ND->getIdentifierNamespace() & IDNS;1511}15121513/// Determines whether this given declaration will be found by1514/// ordinary name lookup but is not a type name.1515bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {1516ND = ND->getUnderlyingDecl();1517if (isa<TypeDecl>(ND))1518return false;1519// Objective-C interfaces names are not filtered by this method because they1520// can be used in a class property expression. We can still filter out1521// @class declarations though.1522if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {1523if (!ID->getDefinition())1524return false;1525}15261527unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;1528if (SemaRef.getLangOpts().CPlusPlus)1529IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;1530else if (SemaRef.getLangOpts().ObjC) {1531if (isa<ObjCIvarDecl>(ND))1532return true;1533}15341535return ND->getIdentifierNamespace() & IDNS;1536}15371538bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {1539if (!IsOrdinaryNonTypeName(ND))1540return false;15411542if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))1543if (VD->getType()->isIntegralOrEnumerationType())1544return true;15451546return false;1547}15481549/// Determines whether this given declaration will be found by1550/// ordinary name lookup.1551bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {1552ND = ND->getUnderlyingDecl();15531554unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;1555if (SemaRef.getLangOpts().CPlusPlus)1556IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;15571558return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&1559!isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);1560}15611562/// Determines whether the given declaration is suitable as the1563/// start of a C++ nested-name-specifier, e.g., a class or namespace.1564bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {1565// Allow us to find class templates, too.1566if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))1567ND = ClassTemplate->getTemplatedDecl();15681569return SemaRef.isAcceptableNestedNameSpecifier(ND);1570}15711572/// Determines whether the given declaration is an enumeration.1573bool ResultBuilder::IsEnum(const NamedDecl *ND) const {1574return isa<EnumDecl>(ND);1575}15761577/// Determines whether the given declaration is a class or struct.1578bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {1579// Allow us to find class templates, too.1580if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))1581ND = ClassTemplate->getTemplatedDecl();15821583// For purposes of this check, interfaces match too.1584if (const auto *RD = dyn_cast<RecordDecl>(ND))1585return RD->getTagKind() == TagTypeKind::Class ||1586RD->getTagKind() == TagTypeKind::Struct ||1587RD->getTagKind() == TagTypeKind::Interface;15881589return false;1590}15911592/// Determines whether the given declaration is a union.1593bool ResultBuilder::IsUnion(const NamedDecl *ND) const {1594// Allow us to find class templates, too.1595if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))1596ND = ClassTemplate->getTemplatedDecl();15971598if (const auto *RD = dyn_cast<RecordDecl>(ND))1599return RD->getTagKind() == TagTypeKind::Union;16001601return false;1602}16031604/// Determines whether the given declaration is a namespace.1605bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {1606return isa<NamespaceDecl>(ND);1607}16081609/// Determines whether the given declaration is a namespace or1610/// namespace alias.1611bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {1612return isa<NamespaceDecl>(ND->getUnderlyingDecl());1613}16141615/// Determines whether the given declaration is a type.1616bool ResultBuilder::IsType(const NamedDecl *ND) const {1617ND = ND->getUnderlyingDecl();1618return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);1619}16201621/// Determines which members of a class should be visible via1622/// "." or "->". Only value declarations, nested name specifiers, and1623/// using declarations thereof should show up.1624bool ResultBuilder::IsMember(const NamedDecl *ND) const {1625ND = ND->getUnderlyingDecl();1626return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||1627isa<ObjCPropertyDecl>(ND);1628}16291630static bool isObjCReceiverType(ASTContext &C, QualType T) {1631T = C.getCanonicalType(T);1632switch (T->getTypeClass()) {1633case Type::ObjCObject:1634case Type::ObjCInterface:1635case Type::ObjCObjectPointer:1636return true;16371638case Type::Builtin:1639switch (cast<BuiltinType>(T)->getKind()) {1640case BuiltinType::ObjCId:1641case BuiltinType::ObjCClass:1642case BuiltinType::ObjCSel:1643return true;16441645default:1646break;1647}1648return false;16491650default:1651break;1652}16531654if (!C.getLangOpts().CPlusPlus)1655return false;16561657// FIXME: We could perform more analysis here to determine whether a1658// particular class type has any conversions to Objective-C types. For now,1659// just accept all class types.1660return T->isDependentType() || T->isRecordType();1661}16621663bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {1664QualType T = getDeclUsageType(SemaRef.Context, ND);1665if (T.isNull())1666return false;16671668T = SemaRef.Context.getBaseElementType(T);1669return isObjCReceiverType(SemaRef.Context, T);1670}16711672bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(1673const NamedDecl *ND) const {1674if (IsObjCMessageReceiver(ND))1675return true;16761677const auto *Var = dyn_cast<VarDecl>(ND);1678if (!Var)1679return false;16801681return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();1682}16831684bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {1685if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||1686(!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))1687return false;16881689QualType T = getDeclUsageType(SemaRef.Context, ND);1690if (T.isNull())1691return false;16921693T = SemaRef.Context.getBaseElementType(T);1694return T->isObjCObjectType() || T->isObjCObjectPointerType() ||1695T->isObjCIdType() ||1696(SemaRef.getLangOpts().CPlusPlus && T->isRecordType());1697}16981699bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {1700return false;1701}17021703/// Determines whether the given declaration is an Objective-C1704/// instance variable.1705bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {1706return isa<ObjCIvarDecl>(ND);1707}17081709namespace {17101711/// Visible declaration consumer that adds a code-completion result1712/// for each visible declaration.1713class CodeCompletionDeclConsumer : public VisibleDeclConsumer {1714ResultBuilder &Results;1715DeclContext *InitialLookupCtx;1716// NamingClass and BaseType are used for access-checking. See1717// Sema::IsSimplyAccessible for details.1718CXXRecordDecl *NamingClass;1719QualType BaseType;1720std::vector<FixItHint> FixIts;17211722public:1723CodeCompletionDeclConsumer(1724ResultBuilder &Results, DeclContext *InitialLookupCtx,1725QualType BaseType = QualType(),1726std::vector<FixItHint> FixIts = std::vector<FixItHint>())1727: Results(Results), InitialLookupCtx(InitialLookupCtx),1728FixIts(std::move(FixIts)) {1729NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);1730// If BaseType was not provided explicitly, emulate implicit 'this->'.1731if (BaseType.isNull()) {1732auto ThisType = Results.getSema().getCurrentThisType();1733if (!ThisType.isNull()) {1734assert(ThisType->isPointerType());1735BaseType = ThisType->getPointeeType();1736if (!NamingClass)1737NamingClass = BaseType->getAsCXXRecordDecl();1738}1739}1740this->BaseType = BaseType;1741}17421743void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,1744bool InBaseClass) override {1745ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,1746false, IsAccessible(ND, Ctx), FixIts);1747Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass, BaseType);1748}17491750void EnteredContext(DeclContext *Ctx) override {1751Results.addVisitedContext(Ctx);1752}17531754private:1755bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {1756// Naming class to use for access check. In most cases it was provided1757// explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),1758// for unqualified lookup we fallback to the \p Ctx in which we found the1759// member.1760auto *NamingClass = this->NamingClass;1761QualType BaseType = this->BaseType;1762if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {1763if (!NamingClass)1764NamingClass = Cls;1765// When we emulate implicit 'this->' in an unqualified lookup, we might1766// end up with an invalid naming class. In that case, we avoid emulating1767// 'this->' qualifier to satisfy preconditions of the access checking.1768if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&1769!NamingClass->isDerivedFrom(Cls)) {1770NamingClass = Cls;1771BaseType = QualType();1772}1773} else {1774// The decl was found outside the C++ class, so only ObjC access checks1775// apply. Those do not rely on NamingClass and BaseType, so we clear them1776// out.1777NamingClass = nullptr;1778BaseType = QualType();1779}1780return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);1781}1782};1783} // namespace17841785/// Add type specifiers for the current language as keyword results.1786static void AddTypeSpecifierResults(const LangOptions &LangOpts,1787ResultBuilder &Results) {1788typedef CodeCompletionResult Result;1789Results.AddResult(Result("short", CCP_Type));1790Results.AddResult(Result("long", CCP_Type));1791Results.AddResult(Result("signed", CCP_Type));1792Results.AddResult(Result("unsigned", CCP_Type));1793Results.AddResult(Result("void", CCP_Type));1794Results.AddResult(Result("char", CCP_Type));1795Results.AddResult(Result("int", CCP_Type));1796Results.AddResult(Result("float", CCP_Type));1797Results.AddResult(Result("double", CCP_Type));1798Results.AddResult(Result("enum", CCP_Type));1799Results.AddResult(Result("struct", CCP_Type));1800Results.AddResult(Result("union", CCP_Type));1801Results.AddResult(Result("const", CCP_Type));1802Results.AddResult(Result("volatile", CCP_Type));18031804if (LangOpts.C99) {1805// C99-specific1806Results.AddResult(Result("_Complex", CCP_Type));1807if (!LangOpts.C2y)1808Results.AddResult(Result("_Imaginary", CCP_Type));1809Results.AddResult(Result("_Bool", CCP_Type));1810Results.AddResult(Result("restrict", CCP_Type));1811}18121813CodeCompletionBuilder Builder(Results.getAllocator(),1814Results.getCodeCompletionTUInfo());1815if (LangOpts.CPlusPlus) {1816// C++-specific1817Results.AddResult(1818Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));1819Results.AddResult(Result("class", CCP_Type));1820Results.AddResult(Result("wchar_t", CCP_Type));18211822// typename name1823Builder.AddTypedTextChunk("typename");1824Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);1825Builder.AddPlaceholderChunk("name");1826Results.AddResult(Result(Builder.TakeString()));18271828if (LangOpts.CPlusPlus11) {1829Results.AddResult(Result("auto", CCP_Type));1830Results.AddResult(Result("char16_t", CCP_Type));1831Results.AddResult(Result("char32_t", CCP_Type));18321833Builder.AddTypedTextChunk("decltype");1834Builder.AddChunk(CodeCompletionString::CK_LeftParen);1835Builder.AddPlaceholderChunk("expression");1836Builder.AddChunk(CodeCompletionString::CK_RightParen);1837Results.AddResult(Result(Builder.TakeString()));1838}1839} else1840Results.AddResult(Result("__auto_type", CCP_Type));18411842// GNU keywords1843if (LangOpts.GNUKeywords) {1844// FIXME: Enable when we actually support decimal floating point.1845// Results.AddResult(Result("_Decimal32"));1846// Results.AddResult(Result("_Decimal64"));1847// Results.AddResult(Result("_Decimal128"));18481849Builder.AddTypedTextChunk("typeof");1850Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);1851Builder.AddPlaceholderChunk("expression");1852Results.AddResult(Result(Builder.TakeString()));18531854Builder.AddTypedTextChunk("typeof");1855Builder.AddChunk(CodeCompletionString::CK_LeftParen);1856Builder.AddPlaceholderChunk("type");1857Builder.AddChunk(CodeCompletionString::CK_RightParen);1858Results.AddResult(Result(Builder.TakeString()));1859}18601861// Nullability1862Results.AddResult(Result("_Nonnull", CCP_Type));1863Results.AddResult(Result("_Null_unspecified", CCP_Type));1864Results.AddResult(Result("_Nullable", CCP_Type));1865}18661867static void1868AddStorageSpecifiers(SemaCodeCompletion::ParserCompletionContext CCC,1869const LangOptions &LangOpts, ResultBuilder &Results) {1870typedef CodeCompletionResult Result;1871// Note: we don't suggest either "auto" or "register", because both1872// are pointless as storage specifiers. Elsewhere, we suggest "auto"1873// in C++0x as a type specifier.1874Results.AddResult(Result("extern"));1875Results.AddResult(Result("static"));18761877if (LangOpts.CPlusPlus11) {1878CodeCompletionAllocator &Allocator = Results.getAllocator();1879CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());18801881// alignas1882Builder.AddTypedTextChunk("alignas");1883Builder.AddChunk(CodeCompletionString::CK_LeftParen);1884Builder.AddPlaceholderChunk("expression");1885Builder.AddChunk(CodeCompletionString::CK_RightParen);1886Results.AddResult(Result(Builder.TakeString()));18871888Results.AddResult(Result("constexpr"));1889Results.AddResult(Result("thread_local"));1890}1891}18921893static void1894AddFunctionSpecifiers(SemaCodeCompletion::ParserCompletionContext CCC,1895const LangOptions &LangOpts, ResultBuilder &Results) {1896typedef CodeCompletionResult Result;1897switch (CCC) {1898case SemaCodeCompletion::PCC_Class:1899case SemaCodeCompletion::PCC_MemberTemplate:1900if (LangOpts.CPlusPlus) {1901Results.AddResult(Result("explicit"));1902Results.AddResult(Result("friend"));1903Results.AddResult(Result("mutable"));1904Results.AddResult(Result("virtual"));1905}1906[[fallthrough]];19071908case SemaCodeCompletion::PCC_ObjCInterface:1909case SemaCodeCompletion::PCC_ObjCImplementation:1910case SemaCodeCompletion::PCC_Namespace:1911case SemaCodeCompletion::PCC_Template:1912if (LangOpts.CPlusPlus || LangOpts.C99)1913Results.AddResult(Result("inline"));1914break;19151916case SemaCodeCompletion::PCC_ObjCInstanceVariableList:1917case SemaCodeCompletion::PCC_Expression:1918case SemaCodeCompletion::PCC_Statement:1919case SemaCodeCompletion::PCC_TopLevelOrExpression:1920case SemaCodeCompletion::PCC_ForInit:1921case SemaCodeCompletion::PCC_Condition:1922case SemaCodeCompletion::PCC_RecoveryInFunction:1923case SemaCodeCompletion::PCC_Type:1924case SemaCodeCompletion::PCC_ParenthesizedExpression:1925case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers:1926break;1927}1928}19291930static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);1931static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);1932static void AddObjCVisibilityResults(const LangOptions &LangOpts,1933ResultBuilder &Results, bool NeedAt);1934static void AddObjCImplementationResults(const LangOptions &LangOpts,1935ResultBuilder &Results, bool NeedAt);1936static void AddObjCInterfaceResults(const LangOptions &LangOpts,1937ResultBuilder &Results, bool NeedAt);1938static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);19391940static void AddTypedefResult(ResultBuilder &Results) {1941CodeCompletionBuilder Builder(Results.getAllocator(),1942Results.getCodeCompletionTUInfo());1943Builder.AddTypedTextChunk("typedef");1944Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);1945Builder.AddPlaceholderChunk("type");1946Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);1947Builder.AddPlaceholderChunk("name");1948Builder.AddChunk(CodeCompletionString::CK_SemiColon);1949Results.AddResult(CodeCompletionResult(Builder.TakeString()));1950}19511952// using name = type1953static void AddUsingAliasResult(CodeCompletionBuilder &Builder,1954ResultBuilder &Results) {1955Builder.AddTypedTextChunk("using");1956Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);1957Builder.AddPlaceholderChunk("name");1958Builder.AddChunk(CodeCompletionString::CK_Equal);1959Builder.AddPlaceholderChunk("type");1960Builder.AddChunk(CodeCompletionString::CK_SemiColon);1961Results.AddResult(CodeCompletionResult(Builder.TakeString()));1962}19631964static bool WantTypesInContext(SemaCodeCompletion::ParserCompletionContext CCC,1965const LangOptions &LangOpts) {1966switch (CCC) {1967case SemaCodeCompletion::PCC_Namespace:1968case SemaCodeCompletion::PCC_Class:1969case SemaCodeCompletion::PCC_ObjCInstanceVariableList:1970case SemaCodeCompletion::PCC_Template:1971case SemaCodeCompletion::PCC_MemberTemplate:1972case SemaCodeCompletion::PCC_Statement:1973case SemaCodeCompletion::PCC_RecoveryInFunction:1974case SemaCodeCompletion::PCC_Type:1975case SemaCodeCompletion::PCC_ParenthesizedExpression:1976case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers:1977case SemaCodeCompletion::PCC_TopLevelOrExpression:1978return true;19791980case SemaCodeCompletion::PCC_Expression:1981case SemaCodeCompletion::PCC_Condition:1982return LangOpts.CPlusPlus;19831984case SemaCodeCompletion::PCC_ObjCInterface:1985case SemaCodeCompletion::PCC_ObjCImplementation:1986return false;19871988case SemaCodeCompletion::PCC_ForInit:1989return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;1990}19911992llvm_unreachable("Invalid ParserCompletionContext!");1993}19941995static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,1996const Preprocessor &PP) {1997PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);1998Policy.AnonymousTagLocations = false;1999Policy.SuppressStrongLifetime = true;2000Policy.SuppressUnwrittenScope = true;2001Policy.SuppressScope = true;2002Policy.CleanUglifiedParameters = true;2003return Policy;2004}20052006/// Retrieve a printing policy suitable for code completion.2007static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {2008return getCompletionPrintingPolicy(S.Context, S.PP);2009}20102011/// Retrieve the string representation of the given type as a string2012/// that has the appropriate lifetime for code completion.2013///2014/// This routine provides a fast path where we provide constant strings for2015/// common type names.2016static const char *GetCompletionTypeString(QualType T, ASTContext &Context,2017const PrintingPolicy &Policy,2018CodeCompletionAllocator &Allocator) {2019if (!T.getLocalQualifiers()) {2020// Built-in type names are constant strings.2021if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))2022return BT->getNameAsCString(Policy);20232024// Anonymous tag types are constant strings.2025if (const TagType *TagT = dyn_cast<TagType>(T))2026if (TagDecl *Tag = TagT->getDecl())2027if (!Tag->hasNameForLinkage()) {2028switch (Tag->getTagKind()) {2029case TagTypeKind::Struct:2030return "struct <anonymous>";2031case TagTypeKind::Interface:2032return "__interface <anonymous>";2033case TagTypeKind::Class:2034return "class <anonymous>";2035case TagTypeKind::Union:2036return "union <anonymous>";2037case TagTypeKind::Enum:2038return "enum <anonymous>";2039}2040}2041}20422043// Slow path: format the type as a string.2044std::string Result;2045T.getAsStringInternal(Result, Policy);2046return Allocator.CopyString(Result);2047}20482049/// Add a completion for "this", if we're in a member function.2050static void addThisCompletion(Sema &S, ResultBuilder &Results) {2051QualType ThisTy = S.getCurrentThisType();2052if (ThisTy.isNull())2053return;20542055CodeCompletionAllocator &Allocator = Results.getAllocator();2056CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());2057PrintingPolicy Policy = getCompletionPrintingPolicy(S);2058Builder.AddResultTypeChunk(2059GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));2060Builder.AddTypedTextChunk("this");2061Results.AddResult(CodeCompletionResult(Builder.TakeString()));2062}20632064static void AddStaticAssertResult(CodeCompletionBuilder &Builder,2065ResultBuilder &Results,2066const LangOptions &LangOpts) {2067if (!LangOpts.CPlusPlus11)2068return;20692070Builder.AddTypedTextChunk("static_assert");2071Builder.AddChunk(CodeCompletionString::CK_LeftParen);2072Builder.AddPlaceholderChunk("expression");2073Builder.AddChunk(CodeCompletionString::CK_Comma);2074Builder.AddPlaceholderChunk("message");2075Builder.AddChunk(CodeCompletionString::CK_RightParen);2076Builder.AddChunk(CodeCompletionString::CK_SemiColon);2077Results.AddResult(CodeCompletionResult(Builder.TakeString()));2078}20792080static void AddOverrideResults(ResultBuilder &Results,2081const CodeCompletionContext &CCContext,2082CodeCompletionBuilder &Builder) {2083Sema &S = Results.getSema();2084const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);2085// If not inside a class/struct/union return empty.2086if (!CR)2087return;2088// First store overrides within current class.2089// These are stored by name to make querying fast in the later step.2090llvm::StringMap<std::vector<FunctionDecl *>> Overrides;2091for (auto *Method : CR->methods()) {2092if (!Method->isVirtual() || !Method->getIdentifier())2093continue;2094Overrides[Method->getName()].push_back(Method);2095}20962097for (const auto &Base : CR->bases()) {2098const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();2099if (!BR)2100continue;2101for (auto *Method : BR->methods()) {2102if (!Method->isVirtual() || !Method->getIdentifier())2103continue;2104const auto it = Overrides.find(Method->getName());2105bool IsOverriden = false;2106if (it != Overrides.end()) {2107for (auto *MD : it->second) {2108// If the method in current body is not an overload of this virtual2109// function, then it overrides this one.2110if (!S.IsOverload(MD, Method, false)) {2111IsOverriden = true;2112break;2113}2114}2115}2116if (!IsOverriden) {2117// Generates a new CodeCompletionResult by taking this function and2118// converting it into an override declaration with only one chunk in the2119// final CodeCompletionString as a TypedTextChunk.2120CodeCompletionResult CCR(Method, 0);2121PrintingPolicy Policy =2122getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());2123auto *CCS = CCR.createCodeCompletionStringForOverride(2124S.getPreprocessor(), S.getASTContext(), Builder,2125/*IncludeBriefComments=*/false, CCContext, Policy);2126Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));2127}2128}2129}2130}21312132/// Add language constructs that show up for "ordinary" names.2133static void2134AddOrdinaryNameResults(SemaCodeCompletion::ParserCompletionContext CCC,2135Scope *S, Sema &SemaRef, ResultBuilder &Results) {2136CodeCompletionAllocator &Allocator = Results.getAllocator();2137CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());21382139typedef CodeCompletionResult Result;2140switch (CCC) {2141case SemaCodeCompletion::PCC_Namespace:2142if (SemaRef.getLangOpts().CPlusPlus) {2143if (Results.includeCodePatterns()) {2144// namespace <identifier> { declarations }2145Builder.AddTypedTextChunk("namespace");2146Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2147Builder.AddPlaceholderChunk("identifier");2148Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2149Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2150Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2151Builder.AddPlaceholderChunk("declarations");2152Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2153Builder.AddChunk(CodeCompletionString::CK_RightBrace);2154Results.AddResult(Result(Builder.TakeString()));2155}21562157// namespace identifier = identifier ;2158Builder.AddTypedTextChunk("namespace");2159Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2160Builder.AddPlaceholderChunk("name");2161Builder.AddChunk(CodeCompletionString::CK_Equal);2162Builder.AddPlaceholderChunk("namespace");2163Builder.AddChunk(CodeCompletionString::CK_SemiColon);2164Results.AddResult(Result(Builder.TakeString()));21652166// Using directives2167Builder.AddTypedTextChunk("using namespace");2168Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2169Builder.AddPlaceholderChunk("identifier");2170Builder.AddChunk(CodeCompletionString::CK_SemiColon);2171Results.AddResult(Result(Builder.TakeString()));21722173// asm(string-literal)2174Builder.AddTypedTextChunk("asm");2175Builder.AddChunk(CodeCompletionString::CK_LeftParen);2176Builder.AddPlaceholderChunk("string-literal");2177Builder.AddChunk(CodeCompletionString::CK_RightParen);2178Results.AddResult(Result(Builder.TakeString()));21792180if (Results.includeCodePatterns()) {2181// Explicit template instantiation2182Builder.AddTypedTextChunk("template");2183Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2184Builder.AddPlaceholderChunk("declaration");2185Results.AddResult(Result(Builder.TakeString()));2186} else {2187Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));2188}2189}21902191if (SemaRef.getLangOpts().ObjC)2192AddObjCTopLevelResults(Results, true);21932194AddTypedefResult(Results);2195[[fallthrough]];21962197case SemaCodeCompletion::PCC_Class:2198if (SemaRef.getLangOpts().CPlusPlus) {2199// Using declaration2200Builder.AddTypedTextChunk("using");2201Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2202Builder.AddPlaceholderChunk("qualifier");2203Builder.AddTextChunk("::");2204Builder.AddPlaceholderChunk("name");2205Builder.AddChunk(CodeCompletionString::CK_SemiColon);2206Results.AddResult(Result(Builder.TakeString()));22072208if (SemaRef.getLangOpts().CPlusPlus11)2209AddUsingAliasResult(Builder, Results);22102211// using typename qualifier::name (only in a dependent context)2212if (SemaRef.CurContext->isDependentContext()) {2213Builder.AddTypedTextChunk("using typename");2214Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2215Builder.AddPlaceholderChunk("qualifier");2216Builder.AddTextChunk("::");2217Builder.AddPlaceholderChunk("name");2218Builder.AddChunk(CodeCompletionString::CK_SemiColon);2219Results.AddResult(Result(Builder.TakeString()));2220}22212222AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());22232224if (CCC == SemaCodeCompletion::PCC_Class) {2225AddTypedefResult(Results);22262227bool IsNotInheritanceScope = !S->isClassInheritanceScope();2228// public:2229Builder.AddTypedTextChunk("public");2230if (IsNotInheritanceScope && Results.includeCodePatterns())2231Builder.AddChunk(CodeCompletionString::CK_Colon);2232Results.AddResult(Result(Builder.TakeString()));22332234// protected:2235Builder.AddTypedTextChunk("protected");2236if (IsNotInheritanceScope && Results.includeCodePatterns())2237Builder.AddChunk(CodeCompletionString::CK_Colon);2238Results.AddResult(Result(Builder.TakeString()));22392240// private:2241Builder.AddTypedTextChunk("private");2242if (IsNotInheritanceScope && Results.includeCodePatterns())2243Builder.AddChunk(CodeCompletionString::CK_Colon);2244Results.AddResult(Result(Builder.TakeString()));22452246// FIXME: This adds override results only if we are at the first word of2247// the declaration/definition. Also call this from other sides to have2248// more use-cases.2249AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,2250Builder);2251}2252}2253[[fallthrough]];22542255case SemaCodeCompletion::PCC_Template:2256case SemaCodeCompletion::PCC_MemberTemplate:2257if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {2258// template < parameters >2259Builder.AddTypedTextChunk("template");2260Builder.AddChunk(CodeCompletionString::CK_LeftAngle);2261Builder.AddPlaceholderChunk("parameters");2262Builder.AddChunk(CodeCompletionString::CK_RightAngle);2263Results.AddResult(Result(Builder.TakeString()));2264} else {2265Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));2266}22672268AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);2269AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);2270break;22712272case SemaCodeCompletion::PCC_ObjCInterface:2273AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);2274AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);2275AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);2276break;22772278case SemaCodeCompletion::PCC_ObjCImplementation:2279AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);2280AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);2281AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);2282break;22832284case SemaCodeCompletion::PCC_ObjCInstanceVariableList:2285AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);2286break;22872288case SemaCodeCompletion::PCC_RecoveryInFunction:2289case SemaCodeCompletion::PCC_TopLevelOrExpression:2290case SemaCodeCompletion::PCC_Statement: {2291if (SemaRef.getLangOpts().CPlusPlus11)2292AddUsingAliasResult(Builder, Results);22932294AddTypedefResult(Results);22952296if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&2297SemaRef.getLangOpts().CXXExceptions) {2298Builder.AddTypedTextChunk("try");2299Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2300Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2301Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2302Builder.AddPlaceholderChunk("statements");2303Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2304Builder.AddChunk(CodeCompletionString::CK_RightBrace);2305Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2306Builder.AddTextChunk("catch");2307Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2308Builder.AddChunk(CodeCompletionString::CK_LeftParen);2309Builder.AddPlaceholderChunk("declaration");2310Builder.AddChunk(CodeCompletionString::CK_RightParen);2311Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2312Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2313Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2314Builder.AddPlaceholderChunk("statements");2315Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2316Builder.AddChunk(CodeCompletionString::CK_RightBrace);2317Results.AddResult(Result(Builder.TakeString()));2318}2319if (SemaRef.getLangOpts().ObjC)2320AddObjCStatementResults(Results, true);23212322if (Results.includeCodePatterns()) {2323// if (condition) { statements }2324Builder.AddTypedTextChunk("if");2325Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2326Builder.AddChunk(CodeCompletionString::CK_LeftParen);2327if (SemaRef.getLangOpts().CPlusPlus)2328Builder.AddPlaceholderChunk("condition");2329else2330Builder.AddPlaceholderChunk("expression");2331Builder.AddChunk(CodeCompletionString::CK_RightParen);2332Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2333Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2334Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2335Builder.AddPlaceholderChunk("statements");2336Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2337Builder.AddChunk(CodeCompletionString::CK_RightBrace);2338Results.AddResult(Result(Builder.TakeString()));23392340// switch (condition) { }2341Builder.AddTypedTextChunk("switch");2342Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2343Builder.AddChunk(CodeCompletionString::CK_LeftParen);2344if (SemaRef.getLangOpts().CPlusPlus)2345Builder.AddPlaceholderChunk("condition");2346else2347Builder.AddPlaceholderChunk("expression");2348Builder.AddChunk(CodeCompletionString::CK_RightParen);2349Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2350Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2351Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2352Builder.AddPlaceholderChunk("cases");2353Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2354Builder.AddChunk(CodeCompletionString::CK_RightBrace);2355Results.AddResult(Result(Builder.TakeString()));2356}23572358// Switch-specific statements.2359if (SemaRef.getCurFunction() &&2360!SemaRef.getCurFunction()->SwitchStack.empty()) {2361// case expression:2362Builder.AddTypedTextChunk("case");2363Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2364Builder.AddPlaceholderChunk("expression");2365Builder.AddChunk(CodeCompletionString::CK_Colon);2366Results.AddResult(Result(Builder.TakeString()));23672368// default:2369Builder.AddTypedTextChunk("default");2370Builder.AddChunk(CodeCompletionString::CK_Colon);2371Results.AddResult(Result(Builder.TakeString()));2372}23732374if (Results.includeCodePatterns()) {2375/// while (condition) { statements }2376Builder.AddTypedTextChunk("while");2377Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2378Builder.AddChunk(CodeCompletionString::CK_LeftParen);2379if (SemaRef.getLangOpts().CPlusPlus)2380Builder.AddPlaceholderChunk("condition");2381else2382Builder.AddPlaceholderChunk("expression");2383Builder.AddChunk(CodeCompletionString::CK_RightParen);2384Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2385Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2386Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2387Builder.AddPlaceholderChunk("statements");2388Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2389Builder.AddChunk(CodeCompletionString::CK_RightBrace);2390Results.AddResult(Result(Builder.TakeString()));23912392// do { statements } while ( expression );2393Builder.AddTypedTextChunk("do");2394Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2395Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2396Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2397Builder.AddPlaceholderChunk("statements");2398Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2399Builder.AddChunk(CodeCompletionString::CK_RightBrace);2400Builder.AddTextChunk("while");2401Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2402Builder.AddChunk(CodeCompletionString::CK_LeftParen);2403Builder.AddPlaceholderChunk("expression");2404Builder.AddChunk(CodeCompletionString::CK_RightParen);2405Results.AddResult(Result(Builder.TakeString()));24062407// for ( for-init-statement ; condition ; expression ) { statements }2408Builder.AddTypedTextChunk("for");2409Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2410Builder.AddChunk(CodeCompletionString::CK_LeftParen);2411if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)2412Builder.AddPlaceholderChunk("init-statement");2413else2414Builder.AddPlaceholderChunk("init-expression");2415Builder.AddChunk(CodeCompletionString::CK_SemiColon);2416Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2417Builder.AddPlaceholderChunk("condition");2418Builder.AddChunk(CodeCompletionString::CK_SemiColon);2419Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2420Builder.AddPlaceholderChunk("inc-expression");2421Builder.AddChunk(CodeCompletionString::CK_RightParen);2422Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2423Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2424Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2425Builder.AddPlaceholderChunk("statements");2426Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2427Builder.AddChunk(CodeCompletionString::CK_RightBrace);2428Results.AddResult(Result(Builder.TakeString()));24292430if (SemaRef.getLangOpts().CPlusPlus11 || SemaRef.getLangOpts().ObjC) {2431// for ( range_declaration (:|in) range_expression ) { statements }2432Builder.AddTypedTextChunk("for");2433Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2434Builder.AddChunk(CodeCompletionString::CK_LeftParen);2435Builder.AddPlaceholderChunk("range-declaration");2436Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2437if (SemaRef.getLangOpts().ObjC)2438Builder.AddTextChunk("in");2439else2440Builder.AddChunk(CodeCompletionString::CK_Colon);2441Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2442Builder.AddPlaceholderChunk("range-expression");2443Builder.AddChunk(CodeCompletionString::CK_RightParen);2444Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2445Builder.AddChunk(CodeCompletionString::CK_LeftBrace);2446Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2447Builder.AddPlaceholderChunk("statements");2448Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);2449Builder.AddChunk(CodeCompletionString::CK_RightBrace);2450Results.AddResult(Result(Builder.TakeString()));2451}2452}24532454if (S->getContinueParent()) {2455// continue ;2456Builder.AddTypedTextChunk("continue");2457Builder.AddChunk(CodeCompletionString::CK_SemiColon);2458Results.AddResult(Result(Builder.TakeString()));2459}24602461if (S->getBreakParent()) {2462// break ;2463Builder.AddTypedTextChunk("break");2464Builder.AddChunk(CodeCompletionString::CK_SemiColon);2465Results.AddResult(Result(Builder.TakeString()));2466}24672468// "return expression ;" or "return ;", depending on the return type.2469QualType ReturnType;2470if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))2471ReturnType = Function->getReturnType();2472else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))2473ReturnType = Method->getReturnType();2474else if (SemaRef.getCurBlock() &&2475!SemaRef.getCurBlock()->ReturnType.isNull())2476ReturnType = SemaRef.getCurBlock()->ReturnType;;2477if (ReturnType.isNull() || ReturnType->isVoidType()) {2478Builder.AddTypedTextChunk("return");2479Builder.AddChunk(CodeCompletionString::CK_SemiColon);2480Results.AddResult(Result(Builder.TakeString()));2481} else {2482assert(!ReturnType.isNull());2483// "return expression ;"2484Builder.AddTypedTextChunk("return");2485Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);2486Builder.AddPlaceholderChunk("expression");2487Builder.AddChunk(CodeCompletionString::CK_SemiColon);2488Results.AddResult(Result(Builder.TakeString()));2489// When boolean, also add 'return true;' and 'return false;'.2490if (ReturnType->isBooleanType()) {2491Builder.AddTypedTextChunk("return true");2492Builder.AddChunk(CodeCompletionString::CK_SemiColon);2493Results.AddResult(Result(Builder.TakeString()));24942495Builder.AddTypedTextChunk("return false");2496Builder.AddChunk(CodeCompletionString::CK_SemiColon);2497Results.AddResult(Result(Builder.TakeString()));2498}2499// For pointers, suggest 'return nullptr' in C++.2500if (SemaRef.getLangOpts().CPlusPlus11 &&2501(ReturnType->isPointerType() || ReturnType->isMemberPointerType())) {2502Builder.AddTypedTextChunk("return nullptr");2503Builder.AddChunk(CodeCompletionString::CK_SemiColon);2504Results.AddResult(Result(Builder.TakeString()));2505}2506}25072508// goto identifier ;2509Builder.AddTypedTextChunk("goto");2510Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2511Builder.AddPlaceholderChunk("label");2512Builder.AddChunk(CodeCompletionString::CK_SemiColon);2513Results.AddResult(Result(Builder.TakeString()));25142515// Using directives2516Builder.AddTypedTextChunk("using namespace");2517Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2518Builder.AddPlaceholderChunk("identifier");2519Builder.AddChunk(CodeCompletionString::CK_SemiColon);2520Results.AddResult(Result(Builder.TakeString()));25212522AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());2523}2524[[fallthrough]];25252526// Fall through (for statement expressions).2527case SemaCodeCompletion::PCC_ForInit:2528case SemaCodeCompletion::PCC_Condition:2529AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);2530// Fall through: conditions and statements can have expressions.2531[[fallthrough]];25322533case SemaCodeCompletion::PCC_ParenthesizedExpression:2534if (SemaRef.getLangOpts().ObjCAutoRefCount &&2535CCC == SemaCodeCompletion::PCC_ParenthesizedExpression) {2536// (__bridge <type>)<expression>2537Builder.AddTypedTextChunk("__bridge");2538Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2539Builder.AddPlaceholderChunk("type");2540Builder.AddChunk(CodeCompletionString::CK_RightParen);2541Builder.AddPlaceholderChunk("expression");2542Results.AddResult(Result(Builder.TakeString()));25432544// (__bridge_transfer <Objective-C type>)<expression>2545Builder.AddTypedTextChunk("__bridge_transfer");2546Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2547Builder.AddPlaceholderChunk("Objective-C type");2548Builder.AddChunk(CodeCompletionString::CK_RightParen);2549Builder.AddPlaceholderChunk("expression");2550Results.AddResult(Result(Builder.TakeString()));25512552// (__bridge_retained <CF type>)<expression>2553Builder.AddTypedTextChunk("__bridge_retained");2554Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2555Builder.AddPlaceholderChunk("CF type");2556Builder.AddChunk(CodeCompletionString::CK_RightParen);2557Builder.AddPlaceholderChunk("expression");2558Results.AddResult(Result(Builder.TakeString()));2559}2560// Fall through2561[[fallthrough]];25622563case SemaCodeCompletion::PCC_Expression: {2564if (SemaRef.getLangOpts().CPlusPlus) {2565// 'this', if we're in a non-static member function.2566addThisCompletion(SemaRef, Results);25672568// true2569Builder.AddResultTypeChunk("bool");2570Builder.AddTypedTextChunk("true");2571Results.AddResult(Result(Builder.TakeString()));25722573// false2574Builder.AddResultTypeChunk("bool");2575Builder.AddTypedTextChunk("false");2576Results.AddResult(Result(Builder.TakeString()));25772578if (SemaRef.getLangOpts().RTTI) {2579// dynamic_cast < type-id > ( expression )2580Builder.AddTypedTextChunk("dynamic_cast");2581Builder.AddChunk(CodeCompletionString::CK_LeftAngle);2582Builder.AddPlaceholderChunk("type");2583Builder.AddChunk(CodeCompletionString::CK_RightAngle);2584Builder.AddChunk(CodeCompletionString::CK_LeftParen);2585Builder.AddPlaceholderChunk("expression");2586Builder.AddChunk(CodeCompletionString::CK_RightParen);2587Results.AddResult(Result(Builder.TakeString()));2588}25892590// static_cast < type-id > ( expression )2591Builder.AddTypedTextChunk("static_cast");2592Builder.AddChunk(CodeCompletionString::CK_LeftAngle);2593Builder.AddPlaceholderChunk("type");2594Builder.AddChunk(CodeCompletionString::CK_RightAngle);2595Builder.AddChunk(CodeCompletionString::CK_LeftParen);2596Builder.AddPlaceholderChunk("expression");2597Builder.AddChunk(CodeCompletionString::CK_RightParen);2598Results.AddResult(Result(Builder.TakeString()));25992600// reinterpret_cast < type-id > ( expression )2601Builder.AddTypedTextChunk("reinterpret_cast");2602Builder.AddChunk(CodeCompletionString::CK_LeftAngle);2603Builder.AddPlaceholderChunk("type");2604Builder.AddChunk(CodeCompletionString::CK_RightAngle);2605Builder.AddChunk(CodeCompletionString::CK_LeftParen);2606Builder.AddPlaceholderChunk("expression");2607Builder.AddChunk(CodeCompletionString::CK_RightParen);2608Results.AddResult(Result(Builder.TakeString()));26092610// const_cast < type-id > ( expression )2611Builder.AddTypedTextChunk("const_cast");2612Builder.AddChunk(CodeCompletionString::CK_LeftAngle);2613Builder.AddPlaceholderChunk("type");2614Builder.AddChunk(CodeCompletionString::CK_RightAngle);2615Builder.AddChunk(CodeCompletionString::CK_LeftParen);2616Builder.AddPlaceholderChunk("expression");2617Builder.AddChunk(CodeCompletionString::CK_RightParen);2618Results.AddResult(Result(Builder.TakeString()));26192620if (SemaRef.getLangOpts().RTTI) {2621// typeid ( expression-or-type )2622Builder.AddResultTypeChunk("std::type_info");2623Builder.AddTypedTextChunk("typeid");2624Builder.AddChunk(CodeCompletionString::CK_LeftParen);2625Builder.AddPlaceholderChunk("expression-or-type");2626Builder.AddChunk(CodeCompletionString::CK_RightParen);2627Results.AddResult(Result(Builder.TakeString()));2628}26292630// new T ( ... )2631Builder.AddTypedTextChunk("new");2632Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2633Builder.AddPlaceholderChunk("type");2634Builder.AddChunk(CodeCompletionString::CK_LeftParen);2635Builder.AddPlaceholderChunk("expressions");2636Builder.AddChunk(CodeCompletionString::CK_RightParen);2637Results.AddResult(Result(Builder.TakeString()));26382639// new T [ ] ( ... )2640Builder.AddTypedTextChunk("new");2641Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2642Builder.AddPlaceholderChunk("type");2643Builder.AddChunk(CodeCompletionString::CK_LeftBracket);2644Builder.AddPlaceholderChunk("size");2645Builder.AddChunk(CodeCompletionString::CK_RightBracket);2646Builder.AddChunk(CodeCompletionString::CK_LeftParen);2647Builder.AddPlaceholderChunk("expressions");2648Builder.AddChunk(CodeCompletionString::CK_RightParen);2649Results.AddResult(Result(Builder.TakeString()));26502651// delete expression2652Builder.AddResultTypeChunk("void");2653Builder.AddTypedTextChunk("delete");2654Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2655Builder.AddPlaceholderChunk("expression");2656Results.AddResult(Result(Builder.TakeString()));26572658// delete [] expression2659Builder.AddResultTypeChunk("void");2660Builder.AddTypedTextChunk("delete");2661Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2662Builder.AddChunk(CodeCompletionString::CK_LeftBracket);2663Builder.AddChunk(CodeCompletionString::CK_RightBracket);2664Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2665Builder.AddPlaceholderChunk("expression");2666Results.AddResult(Result(Builder.TakeString()));26672668if (SemaRef.getLangOpts().CXXExceptions) {2669// throw expression2670Builder.AddResultTypeChunk("void");2671Builder.AddTypedTextChunk("throw");2672Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);2673Builder.AddPlaceholderChunk("expression");2674Results.AddResult(Result(Builder.TakeString()));2675}26762677// FIXME: Rethrow?26782679if (SemaRef.getLangOpts().CPlusPlus11) {2680// nullptr2681Builder.AddResultTypeChunk("std::nullptr_t");2682Builder.AddTypedTextChunk("nullptr");2683Results.AddResult(Result(Builder.TakeString()));26842685// alignof2686Builder.AddResultTypeChunk("size_t");2687Builder.AddTypedTextChunk("alignof");2688Builder.AddChunk(CodeCompletionString::CK_LeftParen);2689Builder.AddPlaceholderChunk("type");2690Builder.AddChunk(CodeCompletionString::CK_RightParen);2691Results.AddResult(Result(Builder.TakeString()));26922693// noexcept2694Builder.AddResultTypeChunk("bool");2695Builder.AddTypedTextChunk("noexcept");2696Builder.AddChunk(CodeCompletionString::CK_LeftParen);2697Builder.AddPlaceholderChunk("expression");2698Builder.AddChunk(CodeCompletionString::CK_RightParen);2699Results.AddResult(Result(Builder.TakeString()));27002701// sizeof... expression2702Builder.AddResultTypeChunk("size_t");2703Builder.AddTypedTextChunk("sizeof...");2704Builder.AddChunk(CodeCompletionString::CK_LeftParen);2705Builder.AddPlaceholderChunk("parameter-pack");2706Builder.AddChunk(CodeCompletionString::CK_RightParen);2707Results.AddResult(Result(Builder.TakeString()));2708}2709}27102711if (SemaRef.getLangOpts().ObjC) {2712// Add "super", if we're in an Objective-C class with a superclass.2713if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {2714// The interface can be NULL.2715if (ObjCInterfaceDecl *ID = Method->getClassInterface())2716if (ID->getSuperClass()) {2717std::string SuperType;2718SuperType = ID->getSuperClass()->getNameAsString();2719if (Method->isInstanceMethod())2720SuperType += " *";27212722Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));2723Builder.AddTypedTextChunk("super");2724Results.AddResult(Result(Builder.TakeString()));2725}2726}27272728AddObjCExpressionResults(Results, true);2729}27302731if (SemaRef.getLangOpts().C11) {2732// _Alignof2733Builder.AddResultTypeChunk("size_t");2734if (SemaRef.PP.isMacroDefined("alignof"))2735Builder.AddTypedTextChunk("alignof");2736else2737Builder.AddTypedTextChunk("_Alignof");2738Builder.AddChunk(CodeCompletionString::CK_LeftParen);2739Builder.AddPlaceholderChunk("type");2740Builder.AddChunk(CodeCompletionString::CK_RightParen);2741Results.AddResult(Result(Builder.TakeString()));2742}27432744if (SemaRef.getLangOpts().C23) {2745// nullptr2746Builder.AddResultTypeChunk("nullptr_t");2747Builder.AddTypedTextChunk("nullptr");2748Results.AddResult(Result(Builder.TakeString()));2749}27502751// sizeof expression2752Builder.AddResultTypeChunk("size_t");2753Builder.AddTypedTextChunk("sizeof");2754Builder.AddChunk(CodeCompletionString::CK_LeftParen);2755Builder.AddPlaceholderChunk("expression-or-type");2756Builder.AddChunk(CodeCompletionString::CK_RightParen);2757Results.AddResult(Result(Builder.TakeString()));2758break;2759}27602761case SemaCodeCompletion::PCC_Type:2762case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers:2763break;2764}27652766if (WantTypesInContext(CCC, SemaRef.getLangOpts()))2767AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);27682769if (SemaRef.getLangOpts().CPlusPlus && CCC != SemaCodeCompletion::PCC_Type)2770Results.AddResult(Result("operator"));2771}27722773/// If the given declaration has an associated type, add it as a result2774/// type chunk.2775static void AddResultTypeChunk(ASTContext &Context,2776const PrintingPolicy &Policy,2777const NamedDecl *ND, QualType BaseType,2778CodeCompletionBuilder &Result) {2779if (!ND)2780return;27812782// Skip constructors and conversion functions, which have their return types2783// built into their names.2784if (isConstructor(ND) || isa<CXXConversionDecl>(ND))2785return;27862787// Determine the type of the declaration (if it has a type).2788QualType T;2789if (const FunctionDecl *Function = ND->getAsFunction())2790T = Function->getReturnType();2791else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {2792if (!BaseType.isNull())2793T = Method->getSendResultType(BaseType);2794else2795T = Method->getReturnType();2796} else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {2797T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));2798T = clang::TypeName::getFullyQualifiedType(T, Context);2799} else if (isa<UnresolvedUsingValueDecl>(ND)) {2800/* Do nothing: ignore unresolved using declarations*/2801} else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {2802if (!BaseType.isNull())2803T = Ivar->getUsageType(BaseType);2804else2805T = Ivar->getType();2806} else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {2807T = Value->getType();2808} else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {2809if (!BaseType.isNull())2810T = Property->getUsageType(BaseType);2811else2812T = Property->getType();2813}28142815if (T.isNull() || Context.hasSameType(T, Context.DependentTy))2816return;28172818Result.AddResultTypeChunk(2819GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));2820}28212822static void MaybeAddSentinel(Preprocessor &PP,2823const NamedDecl *FunctionOrMethod,2824CodeCompletionBuilder &Result) {2825if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())2826if (Sentinel->getSentinel() == 0) {2827if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))2828Result.AddTextChunk(", nil");2829else if (PP.isMacroDefined("NULL"))2830Result.AddTextChunk(", NULL");2831else2832Result.AddTextChunk(", (void*)0");2833}2834}28352836static std::string formatObjCParamQualifiers(unsigned ObjCQuals,2837QualType &Type) {2838std::string Result;2839if (ObjCQuals & Decl::OBJC_TQ_In)2840Result += "in ";2841else if (ObjCQuals & Decl::OBJC_TQ_Inout)2842Result += "inout ";2843else if (ObjCQuals & Decl::OBJC_TQ_Out)2844Result += "out ";2845if (ObjCQuals & Decl::OBJC_TQ_Bycopy)2846Result += "bycopy ";2847else if (ObjCQuals & Decl::OBJC_TQ_Byref)2848Result += "byref ";2849if (ObjCQuals & Decl::OBJC_TQ_Oneway)2850Result += "oneway ";2851if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {2852if (auto nullability = AttributedType::stripOuterNullability(Type)) {2853switch (*nullability) {2854case NullabilityKind::NonNull:2855Result += "nonnull ";2856break;28572858case NullabilityKind::Nullable:2859Result += "nullable ";2860break;28612862case NullabilityKind::Unspecified:2863Result += "null_unspecified ";2864break;28652866case NullabilityKind::NullableResult:2867llvm_unreachable("Not supported as a context-sensitive keyword!");2868break;2869}2870}2871}2872return Result;2873}28742875/// Tries to find the most appropriate type location for an Objective-C2876/// block placeholder.2877///2878/// This function ignores things like typedefs and qualifiers in order to2879/// present the most relevant and accurate block placeholders in code completion2880/// results.2881static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,2882FunctionTypeLoc &Block,2883FunctionProtoTypeLoc &BlockProto,2884bool SuppressBlock = false) {2885if (!TSInfo)2886return;2887TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();2888while (true) {2889// Look through typedefs.2890if (!SuppressBlock) {2891if (TypedefTypeLoc TypedefTL = TL.getAsAdjusted<TypedefTypeLoc>()) {2892if (TypeSourceInfo *InnerTSInfo =2893TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {2894TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();2895continue;2896}2897}28982899// Look through qualified types2900if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {2901TL = QualifiedTL.getUnqualifiedLoc();2902continue;2903}29042905if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {2906TL = AttrTL.getModifiedLoc();2907continue;2908}2909}29102911// Try to get the function prototype behind the block pointer type,2912// then we're done.2913if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {2914TL = BlockPtr.getPointeeLoc().IgnoreParens();2915Block = TL.getAs<FunctionTypeLoc>();2916BlockProto = TL.getAs<FunctionProtoTypeLoc>();2917}2918break;2919}2920}29212922static std::string formatBlockPlaceholder(2923const PrintingPolicy &Policy, const NamedDecl *BlockDecl,2924FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,2925bool SuppressBlockName = false, bool SuppressBlock = false,2926std::optional<ArrayRef<QualType>> ObjCSubsts = std::nullopt);29272928static std::string FormatFunctionParameter(2929const PrintingPolicy &Policy, const DeclaratorDecl *Param,2930bool SuppressName = false, bool SuppressBlock = false,2931std::optional<ArrayRef<QualType>> ObjCSubsts = std::nullopt) {2932// Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.2933// It would be better to pass in the param Type, which is usually available.2934// But this case is rare, so just pretend we fell back to int as elsewhere.2935if (!Param)2936return "int";2937Decl::ObjCDeclQualifier ObjCQual = Decl::OBJC_TQ_None;2938if (const auto *PVD = dyn_cast<ParmVarDecl>(Param))2939ObjCQual = PVD->getObjCDeclQualifier();2940bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());2941if (Param->getType()->isDependentType() ||2942!Param->getType()->isBlockPointerType()) {2943// The argument for a dependent or non-block parameter is a placeholder2944// containing that parameter's type.2945std::string Result;29462947if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)2948Result = std::string(Param->getIdentifier()->deuglifiedName());29492950QualType Type = Param->getType();2951if (ObjCSubsts)2952Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,2953ObjCSubstitutionContext::Parameter);2954if (ObjCMethodParam) {2955Result = "(" + formatObjCParamQualifiers(ObjCQual, Type);2956Result += Type.getAsString(Policy) + ")";2957if (Param->getIdentifier() && !SuppressName)2958Result += Param->getIdentifier()->deuglifiedName();2959} else {2960Type.getAsStringInternal(Result, Policy);2961}2962return Result;2963}29642965// The argument for a block pointer parameter is a block literal with2966// the appropriate type.2967FunctionTypeLoc Block;2968FunctionProtoTypeLoc BlockProto;2969findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,2970SuppressBlock);2971// Try to retrieve the block type information from the property if this is a2972// parameter in a setter.2973if (!Block && ObjCMethodParam &&2974cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {2975if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())2976->findPropertyDecl(/*CheckOverrides=*/false))2977findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,2978SuppressBlock);2979}29802981if (!Block) {2982// We were unable to find a FunctionProtoTypeLoc with parameter names2983// for the block; just use the parameter type as a placeholder.2984std::string Result;2985if (!ObjCMethodParam && Param->getIdentifier())2986Result = std::string(Param->getIdentifier()->deuglifiedName());29872988QualType Type = Param->getType().getUnqualifiedType();29892990if (ObjCMethodParam) {2991Result = Type.getAsString(Policy);2992std::string Quals = formatObjCParamQualifiers(ObjCQual, Type);2993if (!Quals.empty())2994Result = "(" + Quals + " " + Result + ")";2995if (Result.back() != ')')2996Result += " ";2997if (Param->getIdentifier())2998Result += Param->getIdentifier()->deuglifiedName();2999} else {3000Type.getAsStringInternal(Result, Policy);3001}30023003return Result;3004}30053006// We have the function prototype behind the block pointer type, as it was3007// written in the source.3008return formatBlockPlaceholder(Policy, Param, Block, BlockProto,3009/*SuppressBlockName=*/false, SuppressBlock,3010ObjCSubsts);3011}30123013/// Returns a placeholder string that corresponds to an Objective-C block3014/// declaration.3015///3016/// \param BlockDecl A declaration with an Objective-C block type.3017///3018/// \param Block The most relevant type location for that block type.3019///3020/// \param SuppressBlockName Determines whether or not the name of the block3021/// declaration is included in the resulting string.3022static std::string3023formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,3024FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,3025bool SuppressBlockName, bool SuppressBlock,3026std::optional<ArrayRef<QualType>> ObjCSubsts) {3027std::string Result;3028QualType ResultType = Block.getTypePtr()->getReturnType();3029if (ObjCSubsts)3030ResultType =3031ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,3032ObjCSubstitutionContext::Result);3033if (!ResultType->isVoidType() || SuppressBlock)3034ResultType.getAsStringInternal(Result, Policy);30353036// Format the parameter list.3037std::string Params;3038if (!BlockProto || Block.getNumParams() == 0) {3039if (BlockProto && BlockProto.getTypePtr()->isVariadic())3040Params = "(...)";3041else3042Params = "(void)";3043} else {3044Params += "(";3045for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {3046if (I)3047Params += ", ";3048Params += FormatFunctionParameter(Policy, Block.getParam(I),3049/*SuppressName=*/false,3050/*SuppressBlock=*/true, ObjCSubsts);30513052if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())3053Params += ", ...";3054}3055Params += ")";3056}30573058if (SuppressBlock) {3059// Format as a parameter.3060Result = Result + " (^";3061if (!SuppressBlockName && BlockDecl->getIdentifier())3062Result += BlockDecl->getIdentifier()->getName();3063Result += ")";3064Result += Params;3065} else {3066// Format as a block literal argument.3067Result = '^' + Result;3068Result += Params;30693070if (!SuppressBlockName && BlockDecl->getIdentifier())3071Result += BlockDecl->getIdentifier()->getName();3072}30733074return Result;3075}30763077static std::string GetDefaultValueString(const ParmVarDecl *Param,3078const SourceManager &SM,3079const LangOptions &LangOpts) {3080const SourceRange SrcRange = Param->getDefaultArgRange();3081CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);3082bool Invalid = CharSrcRange.isInvalid();3083if (Invalid)3084return "";3085StringRef srcText =3086Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);3087if (Invalid)3088return "";30893090if (srcText.empty() || srcText == "=") {3091// Lexer can't determine the value.3092// This happens if the code is incorrect (for example class is forward3093// declared).3094return "";3095}3096std::string DefValue(srcText.str());3097// FIXME: remove this check if the Lexer::getSourceText value is fixed and3098// this value always has (or always does not have) '=' in front of it3099if (DefValue.at(0) != '=') {3100// If we don't have '=' in front of value.3101// Lexer returns built-in types values without '=' and user-defined types3102// values with it.3103return " = " + DefValue;3104}3105return " " + DefValue;3106}31073108/// Add function parameter chunks to the given code completion string.3109static void AddFunctionParameterChunks(Preprocessor &PP,3110const PrintingPolicy &Policy,3111const FunctionDecl *Function,3112CodeCompletionBuilder &Result,3113unsigned Start = 0,3114bool InOptional = false) {3115bool FirstParameter = true;31163117for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {3118const ParmVarDecl *Param = Function->getParamDecl(P);31193120if (Param->hasDefaultArg() && !InOptional) {3121// When we see an optional default argument, put that argument and3122// the remaining default arguments into a new, optional string.3123CodeCompletionBuilder Opt(Result.getAllocator(),3124Result.getCodeCompletionTUInfo());3125if (!FirstParameter)3126Opt.AddChunk(CodeCompletionString::CK_Comma);3127AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);3128Result.AddOptionalChunk(Opt.TakeString());3129break;3130}31313132if (FirstParameter)3133FirstParameter = false;3134else3135Result.AddChunk(CodeCompletionString::CK_Comma);31363137InOptional = false;31383139// Format the placeholder string.3140std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);3141if (Param->hasDefaultArg())3142PlaceholderStr +=3143GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());31443145if (Function->isVariadic() && P == N - 1)3146PlaceholderStr += ", ...";31473148// Add the placeholder string.3149Result.AddPlaceholderChunk(3150Result.getAllocator().CopyString(PlaceholderStr));3151}31523153if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())3154if (Proto->isVariadic()) {3155if (Proto->getNumParams() == 0)3156Result.AddPlaceholderChunk("...");31573158MaybeAddSentinel(PP, Function, Result);3159}3160}31613162/// Add template parameter chunks to the given code completion string.3163static void AddTemplateParameterChunks(3164ASTContext &Context, const PrintingPolicy &Policy,3165const TemplateDecl *Template, CodeCompletionBuilder &Result,3166unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {3167bool FirstParameter = true;31683169// Prefer to take the template parameter names from the first declaration of3170// the template.3171Template = cast<TemplateDecl>(Template->getCanonicalDecl());31723173TemplateParameterList *Params = Template->getTemplateParameters();3174TemplateParameterList::iterator PEnd = Params->end();3175if (MaxParameters)3176PEnd = Params->begin() + MaxParameters;3177for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;3178++P) {3179bool HasDefaultArg = false;3180std::string PlaceholderStr;3181if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {3182if (TTP->wasDeclaredWithTypename())3183PlaceholderStr = "typename";3184else if (const auto *TC = TTP->getTypeConstraint()) {3185llvm::raw_string_ostream OS(PlaceholderStr);3186TC->print(OS, Policy);3187} else3188PlaceholderStr = "class";31893190if (TTP->getIdentifier()) {3191PlaceholderStr += ' ';3192PlaceholderStr += TTP->getIdentifier()->deuglifiedName();3193}31943195HasDefaultArg = TTP->hasDefaultArgument();3196} else if (NonTypeTemplateParmDecl *NTTP =3197dyn_cast<NonTypeTemplateParmDecl>(*P)) {3198if (NTTP->getIdentifier())3199PlaceholderStr = std::string(NTTP->getIdentifier()->deuglifiedName());3200NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);3201HasDefaultArg = NTTP->hasDefaultArgument();3202} else {3203assert(isa<TemplateTemplateParmDecl>(*P));3204TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);32053206// Since putting the template argument list into the placeholder would3207// be very, very long, we just use an abbreviation.3208PlaceholderStr = "template<...> class";3209if (TTP->getIdentifier()) {3210PlaceholderStr += ' ';3211PlaceholderStr += TTP->getIdentifier()->deuglifiedName();3212}32133214HasDefaultArg = TTP->hasDefaultArgument();3215}32163217if (HasDefaultArg && !InDefaultArg) {3218// When we see an optional default argument, put that argument and3219// the remaining default arguments into a new, optional string.3220CodeCompletionBuilder Opt(Result.getAllocator(),3221Result.getCodeCompletionTUInfo());3222if (!FirstParameter)3223Opt.AddChunk(CodeCompletionString::CK_Comma);3224AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,3225P - Params->begin(), true);3226Result.AddOptionalChunk(Opt.TakeString());3227break;3228}32293230InDefaultArg = false;32313232if (FirstParameter)3233FirstParameter = false;3234else3235Result.AddChunk(CodeCompletionString::CK_Comma);32363237// Add the placeholder string.3238Result.AddPlaceholderChunk(3239Result.getAllocator().CopyString(PlaceholderStr));3240}3241}32423243/// Add a qualifier to the given code-completion string, if the3244/// provided nested-name-specifier is non-NULL.3245static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,3246NestedNameSpecifier *Qualifier,3247bool QualifierIsInformative,3248ASTContext &Context,3249const PrintingPolicy &Policy) {3250if (!Qualifier)3251return;32523253std::string PrintedNNS;3254{3255llvm::raw_string_ostream OS(PrintedNNS);3256Qualifier->print(OS, Policy);3257}3258if (QualifierIsInformative)3259Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));3260else3261Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));3262}32633264static void3265AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,3266const FunctionDecl *Function) {3267const auto *Proto = Function->getType()->getAs<FunctionProtoType>();3268if (!Proto || !Proto->getMethodQuals())3269return;32703271// FIXME: Add ref-qualifier!32723273// Handle single qualifiers without copying3274if (Proto->getMethodQuals().hasOnlyConst()) {3275Result.AddInformativeChunk(" const");3276return;3277}32783279if (Proto->getMethodQuals().hasOnlyVolatile()) {3280Result.AddInformativeChunk(" volatile");3281return;3282}32833284if (Proto->getMethodQuals().hasOnlyRestrict()) {3285Result.AddInformativeChunk(" restrict");3286return;3287}32883289// Handle multiple qualifiers.3290std::string QualsStr;3291if (Proto->isConst())3292QualsStr += " const";3293if (Proto->isVolatile())3294QualsStr += " volatile";3295if (Proto->isRestrict())3296QualsStr += " restrict";3297Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));3298}32993300/// Add the name of the given declaration3301static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,3302const NamedDecl *ND,3303CodeCompletionBuilder &Result) {3304DeclarationName Name = ND->getDeclName();3305if (!Name)3306return;33073308switch (Name.getNameKind()) {3309case DeclarationName::CXXOperatorName: {3310const char *OperatorName = nullptr;3311switch (Name.getCXXOverloadedOperator()) {3312case OO_None:3313case OO_Conditional:3314case NUM_OVERLOADED_OPERATORS:3315OperatorName = "operator";3316break;33173318#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \3319case OO_##Name: \3320OperatorName = "operator" Spelling; \3321break;3322#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)3323#include "clang/Basic/OperatorKinds.def"33243325case OO_New:3326OperatorName = "operator new";3327break;3328case OO_Delete:3329OperatorName = "operator delete";3330break;3331case OO_Array_New:3332OperatorName = "operator new[]";3333break;3334case OO_Array_Delete:3335OperatorName = "operator delete[]";3336break;3337case OO_Call:3338OperatorName = "operator()";3339break;3340case OO_Subscript:3341OperatorName = "operator[]";3342break;3343}3344Result.AddTypedTextChunk(OperatorName);3345break;3346}33473348case DeclarationName::Identifier:3349case DeclarationName::CXXConversionFunctionName:3350case DeclarationName::CXXDestructorName:3351case DeclarationName::CXXLiteralOperatorName:3352Result.AddTypedTextChunk(3353Result.getAllocator().CopyString(ND->getNameAsString()));3354break;33553356case DeclarationName::CXXDeductionGuideName:3357case DeclarationName::CXXUsingDirective:3358case DeclarationName::ObjCZeroArgSelector:3359case DeclarationName::ObjCOneArgSelector:3360case DeclarationName::ObjCMultiArgSelector:3361break;33623363case DeclarationName::CXXConstructorName: {3364CXXRecordDecl *Record = nullptr;3365QualType Ty = Name.getCXXNameType();3366if (const auto *RecordTy = Ty->getAs<RecordType>())3367Record = cast<CXXRecordDecl>(RecordTy->getDecl());3368else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())3369Record = InjectedTy->getDecl();3370else {3371Result.AddTypedTextChunk(3372Result.getAllocator().CopyString(ND->getNameAsString()));3373break;3374}33753376Result.AddTypedTextChunk(3377Result.getAllocator().CopyString(Record->getNameAsString()));3378if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {3379Result.AddChunk(CodeCompletionString::CK_LeftAngle);3380AddTemplateParameterChunks(Context, Policy, Template, Result);3381Result.AddChunk(CodeCompletionString::CK_RightAngle);3382}3383break;3384}3385}3386}33873388CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(3389Sema &S, const CodeCompletionContext &CCContext,3390CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,3391bool IncludeBriefComments) {3392return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,3393CCTUInfo, IncludeBriefComments);3394}33953396CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(3397Preprocessor &PP, CodeCompletionAllocator &Allocator,3398CodeCompletionTUInfo &CCTUInfo) {3399assert(Kind == RK_Macro);3400CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);3401const MacroInfo *MI = PP.getMacroInfo(Macro);3402Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));34033404if (!MI || !MI->isFunctionLike())3405return Result.TakeString();34063407// Format a function-like macro with placeholders for the arguments.3408Result.AddChunk(CodeCompletionString::CK_LeftParen);3409MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();34103411// C99 variadic macros add __VA_ARGS__ at the end. Skip it.3412if (MI->isC99Varargs()) {3413--AEnd;34143415if (A == AEnd) {3416Result.AddPlaceholderChunk("...");3417}3418}34193420for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {3421if (A != MI->param_begin())3422Result.AddChunk(CodeCompletionString::CK_Comma);34233424if (MI->isVariadic() && (A + 1) == AEnd) {3425SmallString<32> Arg = (*A)->getName();3426if (MI->isC99Varargs())3427Arg += ", ...";3428else3429Arg += "...";3430Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));3431break;3432}34333434// Non-variadic macros are simple.3435Result.AddPlaceholderChunk(3436Result.getAllocator().CopyString((*A)->getName()));3437}3438Result.AddChunk(CodeCompletionString::CK_RightParen);3439return Result.TakeString();3440}34413442/// If possible, create a new code completion string for the given3443/// result.3444///3445/// \returns Either a new, heap-allocated code completion string describing3446/// how to use this result, or NULL to indicate that the string or name of the3447/// result is all that is needed.3448CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(3449ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,3450CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,3451bool IncludeBriefComments) {3452if (Kind == RK_Macro)3453return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);34543455CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);34563457PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);3458if (Kind == RK_Pattern) {3459Pattern->Priority = Priority;3460Pattern->Availability = Availability;34613462if (Declaration) {3463Result.addParentContext(Declaration->getDeclContext());3464Pattern->ParentName = Result.getParentName();3465if (const RawComment *RC =3466getPatternCompletionComment(Ctx, Declaration)) {3467Result.addBriefComment(RC->getBriefText(Ctx));3468Pattern->BriefComment = Result.getBriefComment();3469}3470}34713472return Pattern;3473}34743475if (Kind == RK_Keyword) {3476Result.AddTypedTextChunk(Keyword);3477return Result.TakeString();3478}3479assert(Kind == RK_Declaration && "Missed a result kind?");3480return createCodeCompletionStringForDecl(3481PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);3482}34833484static void printOverrideString(const CodeCompletionString &CCS,3485std::string &BeforeName,3486std::string &NameAndSignature) {3487bool SeenTypedChunk = false;3488for (auto &Chunk : CCS) {3489if (Chunk.Kind == CodeCompletionString::CK_Optional) {3490assert(SeenTypedChunk && "optional parameter before name");3491// Note that we put all chunks inside into NameAndSignature.3492printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature);3493continue;3494}3495SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText;3496if (SeenTypedChunk)3497NameAndSignature += Chunk.Text;3498else3499BeforeName += Chunk.Text;3500}3501}35023503CodeCompletionString *3504CodeCompletionResult::createCodeCompletionStringForOverride(3505Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,3506bool IncludeBriefComments, const CodeCompletionContext &CCContext,3507PrintingPolicy &Policy) {3508auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,3509/*IncludeBriefComments=*/false,3510CCContext, Policy);3511std::string BeforeName;3512std::string NameAndSignature;3513// For overrides all chunks go into the result, none are informative.3514printOverrideString(*CCS, BeforeName, NameAndSignature);3515NameAndSignature += " override";35163517Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));3518Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);3519Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature));3520return Result.TakeString();3521}35223523// FIXME: Right now this works well with lambdas. Add support for other functor3524// types like std::function.3525static const NamedDecl *extractFunctorCallOperator(const NamedDecl *ND) {3526const auto *VD = dyn_cast<VarDecl>(ND);3527if (!VD)3528return nullptr;3529const auto *RecordDecl = VD->getType()->getAsCXXRecordDecl();3530if (!RecordDecl || !RecordDecl->isLambda())3531return nullptr;3532return RecordDecl->getLambdaCallOperator();3533}35343535CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(3536Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,3537bool IncludeBriefComments, const CodeCompletionContext &CCContext,3538PrintingPolicy &Policy) {3539const NamedDecl *ND = Declaration;3540Result.addParentContext(ND->getDeclContext());35413542if (IncludeBriefComments) {3543// Add documentation comment, if it exists.3544if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {3545Result.addBriefComment(RC->getBriefText(Ctx));3546}3547}35483549if (StartsNestedNameSpecifier) {3550Result.AddTypedTextChunk(3551Result.getAllocator().CopyString(ND->getNameAsString()));3552Result.AddTextChunk("::");3553return Result.TakeString();3554}35553556for (const auto *I : ND->specific_attrs<AnnotateAttr>())3557Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));35583559auto AddFunctionTypeAndResult = [&](const FunctionDecl *Function) {3560AddResultTypeChunk(Ctx, Policy, Function, CCContext.getBaseType(), Result);3561AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,3562Ctx, Policy);3563AddTypedNameChunk(Ctx, Policy, ND, Result);3564Result.AddChunk(CodeCompletionString::CK_LeftParen);3565AddFunctionParameterChunks(PP, Policy, Function, Result);3566Result.AddChunk(CodeCompletionString::CK_RightParen);3567AddFunctionTypeQualsToCompletionString(Result, Function);3568};35693570if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {3571AddFunctionTypeAndResult(Function);3572return Result.TakeString();3573}35743575if (const auto *CallOperator =3576dyn_cast_or_null<FunctionDecl>(extractFunctorCallOperator(ND))) {3577AddFunctionTypeAndResult(CallOperator);3578return Result.TakeString();3579}35803581AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);35823583if (const FunctionTemplateDecl *FunTmpl =3584dyn_cast<FunctionTemplateDecl>(ND)) {3585AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,3586Ctx, Policy);3587FunctionDecl *Function = FunTmpl->getTemplatedDecl();3588AddTypedNameChunk(Ctx, Policy, Function, Result);35893590// Figure out which template parameters are deduced (or have default3591// arguments).3592// Note that we're creating a non-empty bit vector so that we can go3593// through the loop below to omit default template parameters for non-call3594// cases.3595llvm::SmallBitVector Deduced(FunTmpl->getTemplateParameters()->size());3596// Avoid running it if this is not a call: We should emit *all* template3597// parameters.3598if (FunctionCanBeCall)3599Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);3600unsigned LastDeducibleArgument;3601for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;3602--LastDeducibleArgument) {3603if (!Deduced[LastDeducibleArgument - 1]) {3604// C++0x: Figure out if the template argument has a default. If so,3605// the user doesn't need to type this argument.3606// FIXME: We need to abstract template parameters better!3607bool HasDefaultArg = false;3608NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(3609LastDeducibleArgument - 1);3610if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))3611HasDefaultArg = TTP->hasDefaultArgument();3612else if (NonTypeTemplateParmDecl *NTTP =3613dyn_cast<NonTypeTemplateParmDecl>(Param))3614HasDefaultArg = NTTP->hasDefaultArgument();3615else {3616assert(isa<TemplateTemplateParmDecl>(Param));3617HasDefaultArg =3618cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();3619}36203621if (!HasDefaultArg)3622break;3623}3624}36253626if (LastDeducibleArgument || !FunctionCanBeCall) {3627// Some of the function template arguments cannot be deduced from a3628// function call, so we introduce an explicit template argument list3629// containing all of the arguments up to the first deducible argument.3630//3631// Or, if this isn't a call, emit all the template arguments3632// to disambiguate the (potential) overloads.3633//3634// FIXME: Detect cases where the function parameters can be deduced from3635// the surrounding context, as per [temp.deduct.funcaddr].3636// e.g.,3637// template <class T> void foo(T);3638// void (*f)(int) = foo;3639Result.AddChunk(CodeCompletionString::CK_LeftAngle);3640AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,3641LastDeducibleArgument);3642Result.AddChunk(CodeCompletionString::CK_RightAngle);3643}36443645// Add the function parameters3646Result.AddChunk(CodeCompletionString::CK_LeftParen);3647AddFunctionParameterChunks(PP, Policy, Function, Result);3648Result.AddChunk(CodeCompletionString::CK_RightParen);3649AddFunctionTypeQualsToCompletionString(Result, Function);3650return Result.TakeString();3651}36523653if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {3654AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,3655Ctx, Policy);3656Result.AddTypedTextChunk(3657Result.getAllocator().CopyString(Template->getNameAsString()));3658Result.AddChunk(CodeCompletionString::CK_LeftAngle);3659AddTemplateParameterChunks(Ctx, Policy, Template, Result);3660Result.AddChunk(CodeCompletionString::CK_RightAngle);3661return Result.TakeString();3662}36633664if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {3665Selector Sel = Method->getSelector();3666if (Sel.isUnarySelector()) {3667Result.AddTypedTextChunk(3668Result.getAllocator().CopyString(Sel.getNameForSlot(0)));3669return Result.TakeString();3670}36713672std::string SelName = Sel.getNameForSlot(0).str();3673SelName += ':';3674if (StartParameter == 0)3675Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));3676else {3677Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));36783679// If there is only one parameter, and we're past it, add an empty3680// typed-text chunk since there is nothing to type.3681if (Method->param_size() == 1)3682Result.AddTypedTextChunk("");3683}3684unsigned Idx = 0;3685// The extra Idx < Sel.getNumArgs() check is needed due to legacy C-style3686// method parameters.3687for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),3688PEnd = Method->param_end();3689P != PEnd && Idx < Sel.getNumArgs(); (void)++P, ++Idx) {3690if (Idx > 0) {3691std::string Keyword;3692if (Idx > StartParameter)3693Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);3694if (const IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))3695Keyword += II->getName();3696Keyword += ":";3697if (Idx < StartParameter || AllParametersAreInformative)3698Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));3699else3700Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));3701}37023703// If we're before the starting parameter, skip the placeholder.3704if (Idx < StartParameter)3705continue;37063707std::string Arg;3708QualType ParamType = (*P)->getType();3709std::optional<ArrayRef<QualType>> ObjCSubsts;3710if (!CCContext.getBaseType().isNull())3711ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);37123713if (ParamType->isBlockPointerType() && !DeclaringEntity)3714Arg = FormatFunctionParameter(Policy, *P, true,3715/*SuppressBlock=*/false, ObjCSubsts);3716else {3717if (ObjCSubsts)3718ParamType = ParamType.substObjCTypeArgs(3719Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);3720Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),3721ParamType);3722Arg += ParamType.getAsString(Policy) + ")";3723if (const IdentifierInfo *II = (*P)->getIdentifier())3724if (DeclaringEntity || AllParametersAreInformative)3725Arg += II->getName();3726}37273728if (Method->isVariadic() && (P + 1) == PEnd)3729Arg += ", ...";37303731if (DeclaringEntity)3732Result.AddTextChunk(Result.getAllocator().CopyString(Arg));3733else if (AllParametersAreInformative)3734Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));3735else3736Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));3737}37383739if (Method->isVariadic()) {3740if (Method->param_size() == 0) {3741if (DeclaringEntity)3742Result.AddTextChunk(", ...");3743else if (AllParametersAreInformative)3744Result.AddInformativeChunk(", ...");3745else3746Result.AddPlaceholderChunk(", ...");3747}37483749MaybeAddSentinel(PP, Method, Result);3750}37513752return Result.TakeString();3753}37543755if (Qualifier)3756AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,3757Ctx, Policy);37583759Result.AddTypedTextChunk(3760Result.getAllocator().CopyString(ND->getNameAsString()));3761return Result.TakeString();3762}37633764const RawComment *clang::getCompletionComment(const ASTContext &Ctx,3765const NamedDecl *ND) {3766if (!ND)3767return nullptr;3768if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))3769return RC;37703771// Try to find comment from a property for ObjC methods.3772const auto *M = dyn_cast<ObjCMethodDecl>(ND);3773if (!M)3774return nullptr;3775const ObjCPropertyDecl *PDecl = M->findPropertyDecl();3776if (!PDecl)3777return nullptr;37783779return Ctx.getRawCommentForAnyRedecl(PDecl);3780}37813782const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,3783const NamedDecl *ND) {3784const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);3785if (!M || !M->isPropertyAccessor())3786return nullptr;37873788// Provide code completion comment for self.GetterName where3789// GetterName is the getter method for a property with name3790// different from the property name (declared via a property3791// getter attribute.3792const ObjCPropertyDecl *PDecl = M->findPropertyDecl();3793if (!PDecl)3794return nullptr;3795if (PDecl->getGetterName() == M->getSelector() &&3796PDecl->getIdentifier() != M->getIdentifier()) {3797if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))3798return RC;3799if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))3800return RC;3801}3802return nullptr;3803}38043805const RawComment *clang::getParameterComment(3806const ASTContext &Ctx,3807const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {3808auto FDecl = Result.getFunction();3809if (!FDecl)3810return nullptr;3811if (ArgIndex < FDecl->getNumParams())3812return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));3813return nullptr;3814}38153816static void AddOverloadAggregateChunks(const RecordDecl *RD,3817const PrintingPolicy &Policy,3818CodeCompletionBuilder &Result,3819unsigned CurrentArg) {3820unsigned ChunkIndex = 0;3821auto AddChunk = [&](llvm::StringRef Placeholder) {3822if (ChunkIndex > 0)3823Result.AddChunk(CodeCompletionString::CK_Comma);3824const char *Copy = Result.getAllocator().CopyString(Placeholder);3825if (ChunkIndex == CurrentArg)3826Result.AddCurrentParameterChunk(Copy);3827else3828Result.AddPlaceholderChunk(Copy);3829++ChunkIndex;3830};3831// Aggregate initialization has all bases followed by all fields.3832// (Bases are not legal in C++11 but in that case we never get here).3833if (auto *CRD = llvm::dyn_cast<CXXRecordDecl>(RD)) {3834for (const auto &Base : CRD->bases())3835AddChunk(Base.getType().getAsString(Policy));3836}3837for (const auto &Field : RD->fields())3838AddChunk(FormatFunctionParameter(Policy, Field));3839}38403841/// Add function overload parameter chunks to the given code completion3842/// string.3843static void AddOverloadParameterChunks(3844ASTContext &Context, const PrintingPolicy &Policy,3845const FunctionDecl *Function, const FunctionProtoType *Prototype,3846FunctionProtoTypeLoc PrototypeLoc, CodeCompletionBuilder &Result,3847unsigned CurrentArg, unsigned Start = 0, bool InOptional = false) {3848if (!Function && !Prototype) {3849Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");3850return;3851}38523853bool FirstParameter = true;3854unsigned NumParams =3855Function ? Function->getNumParams() : Prototype->getNumParams();38563857for (unsigned P = Start; P != NumParams; ++P) {3858if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {3859// When we see an optional default argument, put that argument and3860// the remaining default arguments into a new, optional string.3861CodeCompletionBuilder Opt(Result.getAllocator(),3862Result.getCodeCompletionTUInfo());3863if (!FirstParameter)3864Opt.AddChunk(CodeCompletionString::CK_Comma);3865// Optional sections are nested.3866AddOverloadParameterChunks(Context, Policy, Function, Prototype,3867PrototypeLoc, Opt, CurrentArg, P,3868/*InOptional=*/true);3869Result.AddOptionalChunk(Opt.TakeString());3870return;3871}38723873if (FirstParameter)3874FirstParameter = false;3875else3876Result.AddChunk(CodeCompletionString::CK_Comma);38773878InOptional = false;38793880// Format the placeholder string.3881std::string Placeholder;3882assert(P < Prototype->getNumParams());3883if (Function || PrototypeLoc) {3884const ParmVarDecl *Param =3885Function ? Function->getParamDecl(P) : PrototypeLoc.getParam(P);3886Placeholder = FormatFunctionParameter(Policy, Param);3887if (Param->hasDefaultArg())3888Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),3889Context.getLangOpts());3890} else {3891Placeholder = Prototype->getParamType(P).getAsString(Policy);3892}38933894if (P == CurrentArg)3895Result.AddCurrentParameterChunk(3896Result.getAllocator().CopyString(Placeholder));3897else3898Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));3899}39003901if (Prototype && Prototype->isVariadic()) {3902CodeCompletionBuilder Opt(Result.getAllocator(),3903Result.getCodeCompletionTUInfo());3904if (!FirstParameter)3905Opt.AddChunk(CodeCompletionString::CK_Comma);39063907if (CurrentArg < NumParams)3908Opt.AddPlaceholderChunk("...");3909else3910Opt.AddCurrentParameterChunk("...");39113912Result.AddOptionalChunk(Opt.TakeString());3913}3914}39153916static std::string3917formatTemplateParameterPlaceholder(const NamedDecl *Param, bool &Optional,3918const PrintingPolicy &Policy) {3919if (const auto *Type = dyn_cast<TemplateTypeParmDecl>(Param)) {3920Optional = Type->hasDefaultArgument();3921} else if (const auto *NonType = dyn_cast<NonTypeTemplateParmDecl>(Param)) {3922Optional = NonType->hasDefaultArgument();3923} else if (const auto *Template = dyn_cast<TemplateTemplateParmDecl>(Param)) {3924Optional = Template->hasDefaultArgument();3925}3926std::string Result;3927llvm::raw_string_ostream OS(Result);3928Param->print(OS, Policy);3929return Result;3930}39313932static std::string templateResultType(const TemplateDecl *TD,3933const PrintingPolicy &Policy) {3934if (const auto *CTD = dyn_cast<ClassTemplateDecl>(TD))3935return CTD->getTemplatedDecl()->getKindName().str();3936if (const auto *VTD = dyn_cast<VarTemplateDecl>(TD))3937return VTD->getTemplatedDecl()->getType().getAsString(Policy);3938if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(TD))3939return FTD->getTemplatedDecl()->getReturnType().getAsString(Policy);3940if (isa<TypeAliasTemplateDecl>(TD))3941return "type";3942if (isa<TemplateTemplateParmDecl>(TD))3943return "class";3944if (isa<ConceptDecl>(TD))3945return "concept";3946return "";3947}39483949static CodeCompletionString *createTemplateSignatureString(3950const TemplateDecl *TD, CodeCompletionBuilder &Builder, unsigned CurrentArg,3951const PrintingPolicy &Policy) {3952llvm::ArrayRef<NamedDecl *> Params = TD->getTemplateParameters()->asArray();3953CodeCompletionBuilder OptionalBuilder(Builder.getAllocator(),3954Builder.getCodeCompletionTUInfo());3955std::string ResultType = templateResultType(TD, Policy);3956if (!ResultType.empty())3957Builder.AddResultTypeChunk(Builder.getAllocator().CopyString(ResultType));3958Builder.AddTextChunk(3959Builder.getAllocator().CopyString(TD->getNameAsString()));3960Builder.AddChunk(CodeCompletionString::CK_LeftAngle);3961// Initially we're writing into the main string. Once we see an optional arg3962// (with default), we're writing into the nested optional chunk.3963CodeCompletionBuilder *Current = &Builder;3964for (unsigned I = 0; I < Params.size(); ++I) {3965bool Optional = false;3966std::string Placeholder =3967formatTemplateParameterPlaceholder(Params[I], Optional, Policy);3968if (Optional)3969Current = &OptionalBuilder;3970if (I > 0)3971Current->AddChunk(CodeCompletionString::CK_Comma);3972Current->AddChunk(I == CurrentArg3973? CodeCompletionString::CK_CurrentParameter3974: CodeCompletionString::CK_Placeholder,3975Current->getAllocator().CopyString(Placeholder));3976}3977// Add the optional chunk to the main string if we ever used it.3978if (Current == &OptionalBuilder)3979Builder.AddOptionalChunk(OptionalBuilder.TakeString());3980Builder.AddChunk(CodeCompletionString::CK_RightAngle);3981// For function templates, ResultType was the function's return type.3982// Give some clue this is a function. (Don't show the possibly-bulky params).3983if (isa<FunctionTemplateDecl>(TD))3984Builder.AddInformativeChunk("()");3985return Builder.TakeString();3986}39873988CodeCompletionString *3989CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(3990unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,3991CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments,3992bool Braced) const {3993PrintingPolicy Policy = getCompletionPrintingPolicy(S);3994// Show signatures of constructors as they are declared:3995// vector(int n) rather than vector<string>(int n)3996// This is less noisy without being less clear, and avoids tricky cases.3997Policy.SuppressTemplateArgsInCXXConstructors = true;39983999// FIXME: Set priority, availability appropriately.4000CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,4001CXAvailability_Available);40024003if (getKind() == CK_Template)4004return createTemplateSignatureString(getTemplate(), Result, CurrentArg,4005Policy);40064007FunctionDecl *FDecl = getFunction();4008const FunctionProtoType *Proto =4009dyn_cast_or_null<FunctionProtoType>(getFunctionType());40104011// First, the name/type of the callee.4012if (getKind() == CK_Aggregate) {4013Result.AddTextChunk(4014Result.getAllocator().CopyString(getAggregate()->getName()));4015} else if (FDecl) {4016if (IncludeBriefComments) {4017if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))4018Result.addBriefComment(RC->getBriefText(S.getASTContext()));4019}4020AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);40214022std::string Name;4023llvm::raw_string_ostream OS(Name);4024FDecl->getDeclName().print(OS, Policy);4025Result.AddTextChunk(Result.getAllocator().CopyString(Name));4026} else {4027// Function without a declaration. Just give the return type.4028Result.AddResultTypeChunk(Result.getAllocator().CopyString(4029getFunctionType()->getReturnType().getAsString(Policy)));4030}40314032// Next, the brackets and parameters.4033Result.AddChunk(Braced ? CodeCompletionString::CK_LeftBrace4034: CodeCompletionString::CK_LeftParen);4035if (getKind() == CK_Aggregate)4036AddOverloadAggregateChunks(getAggregate(), Policy, Result, CurrentArg);4037else4038AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto,4039getFunctionProtoTypeLoc(), Result, CurrentArg);4040Result.AddChunk(Braced ? CodeCompletionString::CK_RightBrace4041: CodeCompletionString::CK_RightParen);40424043return Result.TakeString();4044}40454046unsigned clang::getMacroUsagePriority(StringRef MacroName,4047const LangOptions &LangOpts,4048bool PreferredTypeIsPointer) {4049unsigned Priority = CCP_Macro;40504051// Treat the "nil", "Nil" and "NULL" macros as null pointer constants.4052if (MacroName == "nil" || MacroName == "NULL" || MacroName == "Nil") {4053Priority = CCP_Constant;4054if (PreferredTypeIsPointer)4055Priority = Priority / CCF_SimilarTypeMatch;4056}4057// Treat "YES", "NO", "true", and "false" as constants.4058else if (MacroName == "YES" || MacroName == "NO" || MacroName == "true" ||4059MacroName == "false")4060Priority = CCP_Constant;4061// Treat "bool" as a type.4062else if (MacroName == "bool")4063Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);40644065return Priority;4066}40674068CXCursorKind clang::getCursorKindForDecl(const Decl *D) {4069if (!D)4070return CXCursor_UnexposedDecl;40714072switch (D->getKind()) {4073case Decl::Enum:4074return CXCursor_EnumDecl;4075case Decl::EnumConstant:4076return CXCursor_EnumConstantDecl;4077case Decl::Field:4078return CXCursor_FieldDecl;4079case Decl::Function:4080return CXCursor_FunctionDecl;4081case Decl::ObjCCategory:4082return CXCursor_ObjCCategoryDecl;4083case Decl::ObjCCategoryImpl:4084return CXCursor_ObjCCategoryImplDecl;4085case Decl::ObjCImplementation:4086return CXCursor_ObjCImplementationDecl;40874088case Decl::ObjCInterface:4089return CXCursor_ObjCInterfaceDecl;4090case Decl::ObjCIvar:4091return CXCursor_ObjCIvarDecl;4092case Decl::ObjCMethod:4093return cast<ObjCMethodDecl>(D)->isInstanceMethod()4094? CXCursor_ObjCInstanceMethodDecl4095: CXCursor_ObjCClassMethodDecl;4096case Decl::CXXMethod:4097return CXCursor_CXXMethod;4098case Decl::CXXConstructor:4099return CXCursor_Constructor;4100case Decl::CXXDestructor:4101return CXCursor_Destructor;4102case Decl::CXXConversion:4103return CXCursor_ConversionFunction;4104case Decl::ObjCProperty:4105return CXCursor_ObjCPropertyDecl;4106case Decl::ObjCProtocol:4107return CXCursor_ObjCProtocolDecl;4108case Decl::ParmVar:4109return CXCursor_ParmDecl;4110case Decl::Typedef:4111return CXCursor_TypedefDecl;4112case Decl::TypeAlias:4113return CXCursor_TypeAliasDecl;4114case Decl::TypeAliasTemplate:4115return CXCursor_TypeAliasTemplateDecl;4116case Decl::Var:4117return CXCursor_VarDecl;4118case Decl::Namespace:4119return CXCursor_Namespace;4120case Decl::NamespaceAlias:4121return CXCursor_NamespaceAlias;4122case Decl::TemplateTypeParm:4123return CXCursor_TemplateTypeParameter;4124case Decl::NonTypeTemplateParm:4125return CXCursor_NonTypeTemplateParameter;4126case Decl::TemplateTemplateParm:4127return CXCursor_TemplateTemplateParameter;4128case Decl::FunctionTemplate:4129return CXCursor_FunctionTemplate;4130case Decl::ClassTemplate:4131return CXCursor_ClassTemplate;4132case Decl::AccessSpec:4133return CXCursor_CXXAccessSpecifier;4134case Decl::ClassTemplatePartialSpecialization:4135return CXCursor_ClassTemplatePartialSpecialization;4136case Decl::UsingDirective:4137return CXCursor_UsingDirective;4138case Decl::StaticAssert:4139return CXCursor_StaticAssert;4140case Decl::Friend:4141return CXCursor_FriendDecl;4142case Decl::TranslationUnit:4143return CXCursor_TranslationUnit;41444145case Decl::Using:4146case Decl::UnresolvedUsingValue:4147case Decl::UnresolvedUsingTypename:4148return CXCursor_UsingDeclaration;41494150case Decl::UsingEnum:4151return CXCursor_EnumDecl;41524153case Decl::ObjCPropertyImpl:4154switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {4155case ObjCPropertyImplDecl::Dynamic:4156return CXCursor_ObjCDynamicDecl;41574158case ObjCPropertyImplDecl::Synthesize:4159return CXCursor_ObjCSynthesizeDecl;4160}4161llvm_unreachable("Unexpected Kind!");41624163case Decl::Import:4164return CXCursor_ModuleImportDecl;41654166case Decl::ObjCTypeParam:4167return CXCursor_TemplateTypeParameter;41684169case Decl::Concept:4170return CXCursor_ConceptDecl;41714172case Decl::LinkageSpec:4173return CXCursor_LinkageSpec;41744175default:4176if (const auto *TD = dyn_cast<TagDecl>(D)) {4177switch (TD->getTagKind()) {4178case TagTypeKind::Interface: // fall through4179case TagTypeKind::Struct:4180return CXCursor_StructDecl;4181case TagTypeKind::Class:4182return CXCursor_ClassDecl;4183case TagTypeKind::Union:4184return CXCursor_UnionDecl;4185case TagTypeKind::Enum:4186return CXCursor_EnumDecl;4187}4188}4189}41904191return CXCursor_UnexposedDecl;4192}41934194static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,4195bool LoadExternal, bool IncludeUndefined,4196bool TargetTypeIsPointer = false) {4197typedef CodeCompletionResult Result;41984199Results.EnterNewScope();42004201for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),4202MEnd = PP.macro_end(LoadExternal);4203M != MEnd; ++M) {4204auto MD = PP.getMacroDefinition(M->first);4205if (IncludeUndefined || MD) {4206MacroInfo *MI = MD.getMacroInfo();4207if (MI && MI->isUsedForHeaderGuard())4208continue;42094210Results.AddResult(4211Result(M->first, MI,4212getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),4213TargetTypeIsPointer)));4214}4215}42164217Results.ExitScope();4218}42194220static void AddPrettyFunctionResults(const LangOptions &LangOpts,4221ResultBuilder &Results) {4222typedef CodeCompletionResult Result;42234224Results.EnterNewScope();42254226Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));4227Results.AddResult(Result("__FUNCTION__", CCP_Constant));4228if (LangOpts.C99 || LangOpts.CPlusPlus11)4229Results.AddResult(Result("__func__", CCP_Constant));4230Results.ExitScope();4231}42324233static void HandleCodeCompleteResults(Sema *S,4234CodeCompleteConsumer *CodeCompleter,4235const CodeCompletionContext &Context,4236CodeCompletionResult *Results,4237unsigned NumResults) {4238if (CodeCompleter)4239CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);4240}42414242static CodeCompletionContext4243mapCodeCompletionContext(Sema &S,4244SemaCodeCompletion::ParserCompletionContext PCC) {4245switch (PCC) {4246case SemaCodeCompletion::PCC_Namespace:4247return CodeCompletionContext::CCC_TopLevel;42484249case SemaCodeCompletion::PCC_Class:4250return CodeCompletionContext::CCC_ClassStructUnion;42514252case SemaCodeCompletion::PCC_ObjCInterface:4253return CodeCompletionContext::CCC_ObjCInterface;42544255case SemaCodeCompletion::PCC_ObjCImplementation:4256return CodeCompletionContext::CCC_ObjCImplementation;42574258case SemaCodeCompletion::PCC_ObjCInstanceVariableList:4259return CodeCompletionContext::CCC_ObjCIvarList;42604261case SemaCodeCompletion::PCC_Template:4262case SemaCodeCompletion::PCC_MemberTemplate:4263if (S.CurContext->isFileContext())4264return CodeCompletionContext::CCC_TopLevel;4265if (S.CurContext->isRecord())4266return CodeCompletionContext::CCC_ClassStructUnion;4267return CodeCompletionContext::CCC_Other;42684269case SemaCodeCompletion::PCC_RecoveryInFunction:4270return CodeCompletionContext::CCC_Recovery;42714272case SemaCodeCompletion::PCC_ForInit:4273if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||4274S.getLangOpts().ObjC)4275return CodeCompletionContext::CCC_ParenthesizedExpression;4276else4277return CodeCompletionContext::CCC_Expression;42784279case SemaCodeCompletion::PCC_Expression:4280return CodeCompletionContext::CCC_Expression;4281case SemaCodeCompletion::PCC_Condition:4282return CodeCompletionContext(CodeCompletionContext::CCC_Expression,4283S.getASTContext().BoolTy);42844285case SemaCodeCompletion::PCC_Statement:4286return CodeCompletionContext::CCC_Statement;42874288case SemaCodeCompletion::PCC_Type:4289return CodeCompletionContext::CCC_Type;42904291case SemaCodeCompletion::PCC_ParenthesizedExpression:4292return CodeCompletionContext::CCC_ParenthesizedExpression;42934294case SemaCodeCompletion::PCC_LocalDeclarationSpecifiers:4295return CodeCompletionContext::CCC_Type;4296case SemaCodeCompletion::PCC_TopLevelOrExpression:4297return CodeCompletionContext::CCC_TopLevelOrExpression;4298}42994300llvm_unreachable("Invalid ParserCompletionContext!");4301}43024303/// If we're in a C++ virtual member function, add completion results4304/// that invoke the functions we override, since it's common to invoke the4305/// overridden function as well as adding new functionality.4306///4307/// \param S The semantic analysis object for which we are generating results.4308///4309/// \param InContext This context in which the nested-name-specifier preceding4310/// the code-completion point4311static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,4312ResultBuilder &Results) {4313// Look through blocks.4314DeclContext *CurContext = S.CurContext;4315while (isa<BlockDecl>(CurContext))4316CurContext = CurContext->getParent();43174318CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);4319if (!Method || !Method->isVirtual())4320return;43214322// We need to have names for all of the parameters, if we're going to4323// generate a forwarding call.4324for (auto *P : Method->parameters())4325if (!P->getDeclName())4326return;43274328PrintingPolicy Policy = getCompletionPrintingPolicy(S);4329for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {4330CodeCompletionBuilder Builder(Results.getAllocator(),4331Results.getCodeCompletionTUInfo());4332if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())4333continue;43344335// If we need a nested-name-specifier, add one now.4336if (!InContext) {4337NestedNameSpecifier *NNS = getRequiredQualification(4338S.Context, CurContext, Overridden->getDeclContext());4339if (NNS) {4340std::string Str;4341llvm::raw_string_ostream OS(Str);4342NNS->print(OS, Policy);4343Builder.AddTextChunk(Results.getAllocator().CopyString(Str));4344}4345} else if (!InContext->Equals(Overridden->getDeclContext()))4346continue;43474348Builder.AddTypedTextChunk(4349Results.getAllocator().CopyString(Overridden->getNameAsString()));4350Builder.AddChunk(CodeCompletionString::CK_LeftParen);4351bool FirstParam = true;4352for (auto *P : Method->parameters()) {4353if (FirstParam)4354FirstParam = false;4355else4356Builder.AddChunk(CodeCompletionString::CK_Comma);43574358Builder.AddPlaceholderChunk(4359Results.getAllocator().CopyString(P->getIdentifier()->getName()));4360}4361Builder.AddChunk(CodeCompletionString::CK_RightParen);4362Results.AddResult(CodeCompletionResult(4363Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,4364CXAvailability_Available, Overridden));4365Results.Ignore(Overridden);4366}4367}43684369void SemaCodeCompletion::CodeCompleteModuleImport(SourceLocation ImportLoc,4370ModuleIdPath Path) {4371typedef CodeCompletionResult Result;4372ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),4373CodeCompleter->getCodeCompletionTUInfo(),4374CodeCompletionContext::CCC_Other);4375Results.EnterNewScope();43764377CodeCompletionAllocator &Allocator = Results.getAllocator();4378CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());4379typedef CodeCompletionResult Result;4380if (Path.empty()) {4381// Enumerate all top-level modules.4382SmallVector<Module *, 8> Modules;4383SemaRef.PP.getHeaderSearchInfo().collectAllModules(Modules);4384for (unsigned I = 0, N = Modules.size(); I != N; ++I) {4385Builder.AddTypedTextChunk(4386Builder.getAllocator().CopyString(Modules[I]->Name));4387Results.AddResult(Result(4388Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,4389Modules[I]->isAvailable() ? CXAvailability_Available4390: CXAvailability_NotAvailable));4391}4392} else if (getLangOpts().Modules) {4393// Load the named module.4394Module *Mod = SemaRef.PP.getModuleLoader().loadModule(4395ImportLoc, Path, Module::AllVisible,4396/*IsInclusionDirective=*/false);4397// Enumerate submodules.4398if (Mod) {4399for (auto *Submodule : Mod->submodules()) {4400Builder.AddTypedTextChunk(4401Builder.getAllocator().CopyString(Submodule->Name));4402Results.AddResult(Result(4403Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,4404Submodule->isAvailable() ? CXAvailability_Available4405: CXAvailability_NotAvailable));4406}4407}4408}4409Results.ExitScope();4410HandleCodeCompleteResults(&SemaRef, CodeCompleter,4411Results.getCompletionContext(), Results.data(),4412Results.size());4413}44144415void SemaCodeCompletion::CodeCompleteOrdinaryName(4416Scope *S, SemaCodeCompletion::ParserCompletionContext CompletionContext) {4417ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),4418CodeCompleter->getCodeCompletionTUInfo(),4419mapCodeCompletionContext(SemaRef, CompletionContext));4420Results.EnterNewScope();44214422// Determine how to filter results, e.g., so that the names of4423// values (functions, enumerators, function templates, etc.) are4424// only allowed where we can have an expression.4425switch (CompletionContext) {4426case PCC_Namespace:4427case PCC_Class:4428case PCC_ObjCInterface:4429case PCC_ObjCImplementation:4430case PCC_ObjCInstanceVariableList:4431case PCC_Template:4432case PCC_MemberTemplate:4433case PCC_Type:4434case PCC_LocalDeclarationSpecifiers:4435Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);4436break;44374438case PCC_Statement:4439case PCC_TopLevelOrExpression:4440case PCC_ParenthesizedExpression:4441case PCC_Expression:4442case PCC_ForInit:4443case PCC_Condition:4444if (WantTypesInContext(CompletionContext, getLangOpts()))4445Results.setFilter(&ResultBuilder::IsOrdinaryName);4446else4447Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);44484449if (getLangOpts().CPlusPlus)4450MaybeAddOverrideCalls(SemaRef, /*InContext=*/nullptr, Results);4451break;44524453case PCC_RecoveryInFunction:4454// Unfiltered4455break;4456}44574458// If we are in a C++ non-static member function, check the qualifiers on4459// the member function to filter/prioritize the results list.4460auto ThisType = SemaRef.getCurrentThisType();4461if (!ThisType.isNull())4462Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(),4463VK_LValue);44644465CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);4466SemaRef.LookupVisibleDecls(S, SemaRef.LookupOrdinaryName, Consumer,4467CodeCompleter->includeGlobals(),4468CodeCompleter->loadExternal());44694470AddOrdinaryNameResults(CompletionContext, S, SemaRef, Results);4471Results.ExitScope();44724473switch (CompletionContext) {4474case PCC_ParenthesizedExpression:4475case PCC_Expression:4476case PCC_Statement:4477case PCC_TopLevelOrExpression:4478case PCC_RecoveryInFunction:4479if (S->getFnParent())4480AddPrettyFunctionResults(getLangOpts(), Results);4481break;44824483case PCC_Namespace:4484case PCC_Class:4485case PCC_ObjCInterface:4486case PCC_ObjCImplementation:4487case PCC_ObjCInstanceVariableList:4488case PCC_Template:4489case PCC_MemberTemplate:4490case PCC_ForInit:4491case PCC_Condition:4492case PCC_Type:4493case PCC_LocalDeclarationSpecifiers:4494break;4495}44964497if (CodeCompleter->includeMacros())4498AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false);44994500HandleCodeCompleteResults(&SemaRef, CodeCompleter,4501Results.getCompletionContext(), Results.data(),4502Results.size());4503}45044505static void4506AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver,4507ArrayRef<const IdentifierInfo *> SelIdents,4508bool AtArgumentExpression, bool IsSuper,4509ResultBuilder &Results);45104511void SemaCodeCompletion::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,4512bool AllowNonIdentifiers,4513bool AllowNestedNameSpecifiers) {4514typedef CodeCompletionResult Result;4515ResultBuilder Results(4516SemaRef, CodeCompleter->getAllocator(),4517CodeCompleter->getCodeCompletionTUInfo(),4518AllowNestedNameSpecifiers4519// FIXME: Try to separate codepath leading here to deduce whether we4520// need an existing symbol or a new one.4521? CodeCompletionContext::CCC_SymbolOrNewName4522: CodeCompletionContext::CCC_NewName);4523Results.EnterNewScope();45244525// Type qualifiers can come after names.4526Results.AddResult(Result("const"));4527Results.AddResult(Result("volatile"));4528if (getLangOpts().C99)4529Results.AddResult(Result("restrict"));45304531if (getLangOpts().CPlusPlus) {4532if (getLangOpts().CPlusPlus11 &&4533(DS.getTypeSpecType() == DeclSpec::TST_class ||4534DS.getTypeSpecType() == DeclSpec::TST_struct))4535Results.AddResult("final");45364537if (AllowNonIdentifiers) {4538Results.AddResult(Result("operator"));4539}45404541// Add nested-name-specifiers.4542if (AllowNestedNameSpecifiers) {4543Results.allowNestedNameSpecifiers();4544Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);4545CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);4546SemaRef.LookupVisibleDecls(S, Sema::LookupNestedNameSpecifierName,4547Consumer, CodeCompleter->includeGlobals(),4548CodeCompleter->loadExternal());4549Results.setFilter(nullptr);4550}4551}4552Results.ExitScope();45534554// If we're in a context where we might have an expression (rather than a4555// declaration), and what we've seen so far is an Objective-C type that could4556// be a receiver of a class message, this may be a class message send with4557// the initial opening bracket '[' missing. Add appropriate completions.4558if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&4559DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&4560DS.getTypeSpecType() == DeclSpec::TST_typename &&4561DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&4562DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified &&4563!DS.isTypeAltiVecVector() && S &&4564(S->getFlags() & Scope::DeclScope) != 0 &&4565(S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |4566Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==45670) {4568ParsedType T = DS.getRepAsType();4569if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())4570AddClassMessageCompletions(SemaRef, S, T, std::nullopt, false, false,4571Results);4572}45734574// Note that we intentionally suppress macro results here, since we do not4575// encourage using macros to produce the names of entities.45764577HandleCodeCompleteResults(&SemaRef, CodeCompleter,4578Results.getCompletionContext(), Results.data(),4579Results.size());4580}45814582static const char *underscoreAttrScope(llvm::StringRef Scope) {4583if (Scope == "clang")4584return "_Clang";4585if (Scope == "gnu")4586return "__gnu__";4587return nullptr;4588}45894590static const char *noUnderscoreAttrScope(llvm::StringRef Scope) {4591if (Scope == "_Clang")4592return "clang";4593if (Scope == "__gnu__")4594return "gnu";4595return nullptr;4596}45974598void SemaCodeCompletion::CodeCompleteAttribute(4599AttributeCommonInfo::Syntax Syntax, AttributeCompletion Completion,4600const IdentifierInfo *InScope) {4601if (Completion == AttributeCompletion::None)4602return;4603ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),4604CodeCompleter->getCodeCompletionTUInfo(),4605CodeCompletionContext::CCC_Attribute);46064607// We're going to iterate over the normalized spellings of the attribute.4608// These don't include "underscore guarding": the normalized spelling is4609// clang::foo but you can also write _Clang::__foo__.4610//4611// (Clang supports a mix like clang::__foo__ but we won't suggest it: either4612// you care about clashing with macros or you don't).4613//4614// So if we're already in a scope, we determine its canonical spellings4615// (for comparison with normalized attr spelling) and remember whether it was4616// underscore-guarded (so we know how to spell contained attributes).4617llvm::StringRef InScopeName;4618bool InScopeUnderscore = false;4619if (InScope) {4620InScopeName = InScope->getName();4621if (const char *NoUnderscore = noUnderscoreAttrScope(InScopeName)) {4622InScopeName = NoUnderscore;4623InScopeUnderscore = true;4624}4625}4626bool SyntaxSupportsGuards = Syntax == AttributeCommonInfo::AS_GNU ||4627Syntax == AttributeCommonInfo::AS_CXX11 ||4628Syntax == AttributeCommonInfo::AS_C23;46294630llvm::DenseSet<llvm::StringRef> FoundScopes;4631auto AddCompletions = [&](const ParsedAttrInfo &A) {4632if (A.IsTargetSpecific &&4633!A.existsInTarget(getASTContext().getTargetInfo()))4634return;4635if (!A.acceptsLangOpts(getLangOpts()))4636return;4637for (const auto &S : A.Spellings) {4638if (S.Syntax != Syntax)4639continue;4640llvm::StringRef Name = S.NormalizedFullName;4641llvm::StringRef Scope;4642if ((Syntax == AttributeCommonInfo::AS_CXX11 ||4643Syntax == AttributeCommonInfo::AS_C23)) {4644std::tie(Scope, Name) = Name.split("::");4645if (Name.empty()) // oops, unscoped4646std::swap(Name, Scope);4647}46484649// Do we just want a list of scopes rather than attributes?4650if (Completion == AttributeCompletion::Scope) {4651// Make sure to emit each scope only once.4652if (!Scope.empty() && FoundScopes.insert(Scope).second) {4653Results.AddResult(4654CodeCompletionResult(Results.getAllocator().CopyString(Scope)));4655// Include alternate form (__gnu__ instead of gnu).4656if (const char *Scope2 = underscoreAttrScope(Scope))4657Results.AddResult(CodeCompletionResult(Scope2));4658}4659continue;4660}46614662// If a scope was specified, it must match but we don't need to print it.4663if (!InScopeName.empty()) {4664if (Scope != InScopeName)4665continue;4666Scope = "";4667}46684669auto Add = [&](llvm::StringRef Scope, llvm::StringRef Name,4670bool Underscores) {4671CodeCompletionBuilder Builder(Results.getAllocator(),4672Results.getCodeCompletionTUInfo());4673llvm::SmallString<32> Text;4674if (!Scope.empty()) {4675Text.append(Scope);4676Text.append("::");4677}4678if (Underscores)4679Text.append("__");4680Text.append(Name);4681if (Underscores)4682Text.append("__");4683Builder.AddTypedTextChunk(Results.getAllocator().CopyString(Text));46844685if (!A.ArgNames.empty()) {4686Builder.AddChunk(CodeCompletionString::CK_LeftParen, "(");4687bool First = true;4688for (const char *Arg : A.ArgNames) {4689if (!First)4690Builder.AddChunk(CodeCompletionString::CK_Comma, ", ");4691First = false;4692Builder.AddPlaceholderChunk(Arg);4693}4694Builder.AddChunk(CodeCompletionString::CK_RightParen, ")");4695}46964697Results.AddResult(Builder.TakeString());4698};46994700// Generate the non-underscore-guarded result.4701// Note this is (a suffix of) the NormalizedFullName, no need to copy.4702// If an underscore-guarded scope was specified, only the4703// underscore-guarded attribute name is relevant.4704if (!InScopeUnderscore)4705Add(Scope, Name, /*Underscores=*/false);47064707// Generate the underscore-guarded version, for syntaxes that support it.4708// We skip this if the scope was already spelled and not guarded, or4709// we must spell it and can't guard it.4710if (!(InScope && !InScopeUnderscore) && SyntaxSupportsGuards) {4711llvm::SmallString<32> Guarded;4712if (Scope.empty()) {4713Add(Scope, Name, /*Underscores=*/true);4714} else {4715const char *GuardedScope = underscoreAttrScope(Scope);4716if (!GuardedScope)4717continue;4718Add(GuardedScope, Name, /*Underscores=*/true);4719}4720}47214722// It may be nice to include the Kind so we can look up the docs later.4723}4724};47254726for (const auto *A : ParsedAttrInfo::getAllBuiltin())4727AddCompletions(*A);4728for (const auto &Entry : ParsedAttrInfoRegistry::entries())4729AddCompletions(*Entry.instantiate());47304731HandleCodeCompleteResults(&SemaRef, CodeCompleter,4732Results.getCompletionContext(), Results.data(),4733Results.size());4734}47354736struct SemaCodeCompletion::CodeCompleteExpressionData {4737CodeCompleteExpressionData(QualType PreferredType = QualType(),4738bool IsParenthesized = false)4739: PreferredType(PreferredType), IntegralConstantExpression(false),4740ObjCCollection(false), IsParenthesized(IsParenthesized) {}47414742QualType PreferredType;4743bool IntegralConstantExpression;4744bool ObjCCollection;4745bool IsParenthesized;4746SmallVector<Decl *, 4> IgnoreDecls;4747};47484749namespace {4750/// Information that allows to avoid completing redundant enumerators.4751struct CoveredEnumerators {4752llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;4753NestedNameSpecifier *SuggestedQualifier = nullptr;4754};4755} // namespace47564757static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,4758EnumDecl *Enum, DeclContext *CurContext,4759const CoveredEnumerators &Enumerators) {4760NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;4761if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {4762// If there are no prior enumerators in C++, check whether we have to4763// qualify the names of the enumerators that we suggest, because they4764// may not be visible in this scope.4765Qualifier = getRequiredQualification(Context, CurContext, Enum);4766}47674768Results.EnterNewScope();4769for (auto *E : Enum->enumerators()) {4770if (Enumerators.Seen.count(E))4771continue;47724773CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);4774Results.AddResult(R, CurContext, nullptr, false);4775}4776Results.ExitScope();4777}47784779/// Try to find a corresponding FunctionProtoType for function-like types (e.g.4780/// function pointers, std::function, etc).4781static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) {4782assert(!T.isNull());4783// Try to extract first template argument from std::function<> and similar.4784// Note we only handle the sugared types, they closely match what users wrote.4785// We explicitly choose to not handle ClassTemplateSpecializationDecl.4786if (auto *Specialization = T->getAs<TemplateSpecializationType>()) {4787if (Specialization->template_arguments().size() != 1)4788return nullptr;4789const TemplateArgument &Argument = Specialization->template_arguments()[0];4790if (Argument.getKind() != TemplateArgument::Type)4791return nullptr;4792return Argument.getAsType()->getAs<FunctionProtoType>();4793}4794// Handle other cases.4795if (T->isPointerType())4796T = T->getPointeeType();4797return T->getAs<FunctionProtoType>();4798}47994800/// Adds a pattern completion for a lambda expression with the specified4801/// parameter types and placeholders for parameter names.4802static void AddLambdaCompletion(ResultBuilder &Results,4803llvm::ArrayRef<QualType> Parameters,4804const LangOptions &LangOpts) {4805if (!Results.includeCodePatterns())4806return;4807CodeCompletionBuilder Completion(Results.getAllocator(),4808Results.getCodeCompletionTUInfo());4809// [](<parameters>) {}4810Completion.AddChunk(CodeCompletionString::CK_LeftBracket);4811Completion.AddPlaceholderChunk("=");4812Completion.AddChunk(CodeCompletionString::CK_RightBracket);4813if (!Parameters.empty()) {4814Completion.AddChunk(CodeCompletionString::CK_LeftParen);4815bool First = true;4816for (auto Parameter : Parameters) {4817if (!First)4818Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma);4819else4820First = false;48214822constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!";4823std::string Type = std::string(NamePlaceholder);4824Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts));4825llvm::StringRef Prefix, Suffix;4826std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder);4827Prefix = Prefix.rtrim();4828Suffix = Suffix.ltrim();48294830Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix));4831Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);4832Completion.AddPlaceholderChunk("parameter");4833Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix));4834};4835Completion.AddChunk(CodeCompletionString::CK_RightParen);4836}4837Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);4838Completion.AddChunk(CodeCompletionString::CK_LeftBrace);4839Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);4840Completion.AddPlaceholderChunk("body");4841Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);4842Completion.AddChunk(CodeCompletionString::CK_RightBrace);48434844Results.AddResult(Completion.TakeString());4845}48464847/// Perform code-completion in an expression context when we know what4848/// type we're looking for.4849void SemaCodeCompletion::CodeCompleteExpression(4850Scope *S, const CodeCompleteExpressionData &Data) {4851ResultBuilder Results(4852SemaRef, CodeCompleter->getAllocator(),4853CodeCompleter->getCodeCompletionTUInfo(),4854CodeCompletionContext(4855Data.IsParenthesized4856? CodeCompletionContext::CCC_ParenthesizedExpression4857: CodeCompletionContext::CCC_Expression,4858Data.PreferredType));4859auto PCC =4860Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;4861if (Data.ObjCCollection)4862Results.setFilter(&ResultBuilder::IsObjCCollection);4863else if (Data.IntegralConstantExpression)4864Results.setFilter(&ResultBuilder::IsIntegralConstantValue);4865else if (WantTypesInContext(PCC, getLangOpts()))4866Results.setFilter(&ResultBuilder::IsOrdinaryName);4867else4868Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);48694870if (!Data.PreferredType.isNull())4871Results.setPreferredType(Data.PreferredType.getNonReferenceType());48724873// Ignore any declarations that we were told that we don't care about.4874for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)4875Results.Ignore(Data.IgnoreDecls[I]);48764877CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);4878SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,4879CodeCompleter->includeGlobals(),4880CodeCompleter->loadExternal());48814882Results.EnterNewScope();4883AddOrdinaryNameResults(PCC, S, SemaRef, Results);4884Results.ExitScope();48854886bool PreferredTypeIsPointer = false;4887if (!Data.PreferredType.isNull()) {4888PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||4889Data.PreferredType->isMemberPointerType() ||4890Data.PreferredType->isBlockPointerType();4891if (Data.PreferredType->isEnumeralType()) {4892EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();4893if (auto *Def = Enum->getDefinition())4894Enum = Def;4895// FIXME: collect covered enumerators in cases like:4896// if (x == my_enum::one) { ... } else if (x == ^) {}4897AddEnumerators(Results, getASTContext(), Enum, SemaRef.CurContext,4898CoveredEnumerators());4899}4900}49014902if (S->getFnParent() && !Data.ObjCCollection &&4903!Data.IntegralConstantExpression)4904AddPrettyFunctionResults(getLangOpts(), Results);49054906if (CodeCompleter->includeMacros())4907AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false,4908PreferredTypeIsPointer);49094910// Complete a lambda expression when preferred type is a function.4911if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) {4912if (const FunctionProtoType *F =4913TryDeconstructFunctionLike(Data.PreferredType))4914AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts());4915}49164917HandleCodeCompleteResults(&SemaRef, CodeCompleter,4918Results.getCompletionContext(), Results.data(),4919Results.size());4920}49214922void SemaCodeCompletion::CodeCompleteExpression(Scope *S,4923QualType PreferredType,4924bool IsParenthesized) {4925return CodeCompleteExpression(4926S, CodeCompleteExpressionData(PreferredType, IsParenthesized));4927}49284929void SemaCodeCompletion::CodeCompletePostfixExpression(Scope *S, ExprResult E,4930QualType PreferredType) {4931if (E.isInvalid())4932CodeCompleteExpression(S, PreferredType);4933else if (getLangOpts().ObjC)4934CodeCompleteObjCInstanceMessage(S, E.get(), std::nullopt, false);4935}49364937/// The set of properties that have already been added, referenced by4938/// property name.4939typedef llvm::SmallPtrSet<const IdentifierInfo *, 16> AddedPropertiesSet;49404941/// Retrieve the container definition, if any?4942static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {4943if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {4944if (Interface->hasDefinition())4945return Interface->getDefinition();49464947return Interface;4948}49494950if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {4951if (Protocol->hasDefinition())4952return Protocol->getDefinition();49534954return Protocol;4955}4956return Container;4957}49584959/// Adds a block invocation code completion result for the given block4960/// declaration \p BD.4961static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,4962CodeCompletionBuilder &Builder,4963const NamedDecl *BD,4964const FunctionTypeLoc &BlockLoc,4965const FunctionProtoTypeLoc &BlockProtoLoc) {4966Builder.AddResultTypeChunk(4967GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,4968Policy, Builder.getAllocator()));49694970AddTypedNameChunk(Context, Policy, BD, Builder);4971Builder.AddChunk(CodeCompletionString::CK_LeftParen);49724973if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {4974Builder.AddPlaceholderChunk("...");4975} else {4976for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {4977if (I)4978Builder.AddChunk(CodeCompletionString::CK_Comma);49794980// Format the placeholder string.4981std::string PlaceholderStr =4982FormatFunctionParameter(Policy, BlockLoc.getParam(I));49834984if (I == N - 1 && BlockProtoLoc &&4985BlockProtoLoc.getTypePtr()->isVariadic())4986PlaceholderStr += ", ...";49874988// Add the placeholder string.4989Builder.AddPlaceholderChunk(4990Builder.getAllocator().CopyString(PlaceholderStr));4991}4992}49934994Builder.AddChunk(CodeCompletionString::CK_RightParen);4995}49964997static void4998AddObjCProperties(const CodeCompletionContext &CCContext,4999ObjCContainerDecl *Container, bool AllowCategories,5000bool AllowNullaryMethods, DeclContext *CurContext,5001AddedPropertiesSet &AddedProperties, ResultBuilder &Results,5002bool IsBaseExprStatement = false,5003bool IsClassProperty = false, bool InOriginalClass = true) {5004typedef CodeCompletionResult Result;50055006// Retrieve the definition.5007Container = getContainerDef(Container);50085009// Add properties in this container.5010const auto AddProperty = [&](const ObjCPropertyDecl *P) {5011if (!AddedProperties.insert(P->getIdentifier()).second)5012return;50135014// FIXME: Provide block invocation completion for non-statement5015// expressions.5016if (!P->getType().getTypePtr()->isBlockPointerType() ||5017!IsBaseExprStatement) {5018Result R = Result(P, Results.getBasePriority(P), nullptr);5019if (!InOriginalClass)5020setInBaseClass(R);5021Results.MaybeAddResult(R, CurContext);5022return;5023}50245025// Block setter and invocation completion is provided only when we are able5026// to find the FunctionProtoTypeLoc with parameter names for the block.5027FunctionTypeLoc BlockLoc;5028FunctionProtoTypeLoc BlockProtoLoc;5029findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,5030BlockProtoLoc);5031if (!BlockLoc) {5032Result R = Result(P, Results.getBasePriority(P), nullptr);5033if (!InOriginalClass)5034setInBaseClass(R);5035Results.MaybeAddResult(R, CurContext);5036return;5037}50385039// The default completion result for block properties should be the block5040// invocation completion when the base expression is a statement.5041CodeCompletionBuilder Builder(Results.getAllocator(),5042Results.getCodeCompletionTUInfo());5043AddObjCBlockCall(Container->getASTContext(),5044getCompletionPrintingPolicy(Results.getSema()), Builder, P,5045BlockLoc, BlockProtoLoc);5046Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));5047if (!InOriginalClass)5048setInBaseClass(R);5049Results.MaybeAddResult(R, CurContext);50505051// Provide additional block setter completion iff the base expression is a5052// statement and the block property is mutable.5053if (!P->isReadOnly()) {5054CodeCompletionBuilder Builder(Results.getAllocator(),5055Results.getCodeCompletionTUInfo());5056AddResultTypeChunk(Container->getASTContext(),5057getCompletionPrintingPolicy(Results.getSema()), P,5058CCContext.getBaseType(), Builder);5059Builder.AddTypedTextChunk(5060Results.getAllocator().CopyString(P->getName()));5061Builder.AddChunk(CodeCompletionString::CK_Equal);50625063std::string PlaceholderStr = formatBlockPlaceholder(5064getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,5065BlockProtoLoc, /*SuppressBlockName=*/true);5066// Add the placeholder string.5067Builder.AddPlaceholderChunk(5068Builder.getAllocator().CopyString(PlaceholderStr));50695070// When completing blocks properties that return void the default5071// property completion result should show up before the setter,5072// otherwise the setter completion should show up before the default5073// property completion, as we normally want to use the result of the5074// call.5075Result R =5076Result(Builder.TakeString(), P,5077Results.getBasePriority(P) +5078(BlockLoc.getTypePtr()->getReturnType()->isVoidType()5079? CCD_BlockPropertySetter5080: -CCD_BlockPropertySetter));5081if (!InOriginalClass)5082setInBaseClass(R);5083Results.MaybeAddResult(R, CurContext);5084}5085};50865087if (IsClassProperty) {5088for (const auto *P : Container->class_properties())5089AddProperty(P);5090} else {5091for (const auto *P : Container->instance_properties())5092AddProperty(P);5093}50945095// Add nullary methods or implicit class properties5096if (AllowNullaryMethods) {5097ASTContext &Context = Container->getASTContext();5098PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());5099// Adds a method result5100const auto AddMethod = [&](const ObjCMethodDecl *M) {5101const IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);5102if (!Name)5103return;5104if (!AddedProperties.insert(Name).second)5105return;5106CodeCompletionBuilder Builder(Results.getAllocator(),5107Results.getCodeCompletionTUInfo());5108AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);5109Builder.AddTypedTextChunk(5110Results.getAllocator().CopyString(Name->getName()));5111Result R = Result(Builder.TakeString(), M,5112CCP_MemberDeclaration + CCD_MethodAsProperty);5113if (!InOriginalClass)5114setInBaseClass(R);5115Results.MaybeAddResult(R, CurContext);5116};51175118if (IsClassProperty) {5119for (const auto *M : Container->methods()) {5120// Gather the class method that can be used as implicit property5121// getters. Methods with arguments or methods that return void aren't5122// added to the results as they can't be used as a getter.5123if (!M->getSelector().isUnarySelector() ||5124M->getReturnType()->isVoidType() || M->isInstanceMethod())5125continue;5126AddMethod(M);5127}5128} else {5129for (auto *M : Container->methods()) {5130if (M->getSelector().isUnarySelector())5131AddMethod(M);5132}5133}5134}51355136// Add properties in referenced protocols.5137if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {5138for (auto *P : Protocol->protocols())5139AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,5140CurContext, AddedProperties, Results,5141IsBaseExprStatement, IsClassProperty,5142/*InOriginalClass*/ false);5143} else if (ObjCInterfaceDecl *IFace =5144dyn_cast<ObjCInterfaceDecl>(Container)) {5145if (AllowCategories) {5146// Look through categories.5147for (auto *Cat : IFace->known_categories())5148AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,5149CurContext, AddedProperties, Results,5150IsBaseExprStatement, IsClassProperty,5151InOriginalClass);5152}51535154// Look through protocols.5155for (auto *I : IFace->all_referenced_protocols())5156AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,5157CurContext, AddedProperties, Results,5158IsBaseExprStatement, IsClassProperty,5159/*InOriginalClass*/ false);51605161// Look in the superclass.5162if (IFace->getSuperClass())5163AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,5164AllowNullaryMethods, CurContext, AddedProperties,5165Results, IsBaseExprStatement, IsClassProperty,5166/*InOriginalClass*/ false);5167} else if (const auto *Category =5168dyn_cast<ObjCCategoryDecl>(Container)) {5169// Look through protocols.5170for (auto *P : Category->protocols())5171AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,5172CurContext, AddedProperties, Results,5173IsBaseExprStatement, IsClassProperty,5174/*InOriginalClass*/ false);5175}5176}51775178static void5179AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,5180Scope *S, QualType BaseType,5181ExprValueKind BaseKind, RecordDecl *RD,5182std::optional<FixItHint> AccessOpFixIt) {5183// Indicate that we are performing a member access, and the cv-qualifiers5184// for the base object type.5185Results.setObjectTypeQualifiers(BaseType.getQualifiers(), BaseKind);51865187// Access to a C/C++ class, struct, or union.5188Results.allowNestedNameSpecifiers();5189std::vector<FixItHint> FixIts;5190if (AccessOpFixIt)5191FixIts.emplace_back(*AccessOpFixIt);5192CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));5193SemaRef.LookupVisibleDecls(5194RD, Sema::LookupMemberName, Consumer,5195SemaRef.CodeCompletion().CodeCompleter->includeGlobals(),5196/*IncludeDependentBases=*/true,5197SemaRef.CodeCompletion().CodeCompleter->loadExternal());51985199if (SemaRef.getLangOpts().CPlusPlus) {5200if (!Results.empty()) {5201// The "template" keyword can follow "->" or "." in the grammar.5202// However, we only want to suggest the template keyword if something5203// is dependent.5204bool IsDependent = BaseType->isDependentType();5205if (!IsDependent) {5206for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())5207if (DeclContext *Ctx = DepScope->getEntity()) {5208IsDependent = Ctx->isDependentContext();5209break;5210}5211}52125213if (IsDependent)5214Results.AddResult(CodeCompletionResult("template"));5215}5216}5217}52185219// Returns the RecordDecl inside the BaseType, falling back to primary template5220// in case of specializations. Since we might not have a decl for the5221// instantiation/specialization yet, e.g. dependent code.5222static RecordDecl *getAsRecordDecl(QualType BaseType) {5223BaseType = BaseType.getNonReferenceType();5224if (auto *RD = BaseType->getAsRecordDecl()) {5225if (const auto *CTSD =5226llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) {5227// Template might not be instantiated yet, fall back to primary template5228// in such cases.5229if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared)5230RD = CTSD->getSpecializedTemplate()->getTemplatedDecl();5231}5232return RD;5233}52345235if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {5236if (const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(5237TST->getTemplateName().getAsTemplateDecl())) {5238return TD->getTemplatedDecl();5239}5240}52415242return nullptr;5243}52445245namespace {5246// Collects completion-relevant information about a concept-constrainted type T.5247// In particular, examines the constraint expressions to find members of T.5248//5249// The design is very simple: we walk down each constraint looking for5250// expressions of the form T.foo().5251// If we're extra lucky, the return type is specified.5252// We don't do any clever handling of && or || in constraint expressions, we5253// take members from both branches.5254//5255// For example, given:5256// template <class T> concept X = requires (T t, string& s) { t.print(s); };5257// template <X U> void foo(U u) { u.^ }5258// We want to suggest the inferred member function 'print(string)'.5259// We see that u has type U, so X<U> holds.5260// X<U> requires t.print(s) to be valid, where t has type U (substituted for T).5261// By looking at the CallExpr we find the signature of print().5262//5263// While we tend to know in advance which kind of members (access via . -> ::)5264// we want, it's simpler just to gather them all and post-filter.5265//5266// FIXME: some of this machinery could be used for non-concept type-parms too,5267// enabling completion for type parameters based on other uses of that param.5268//5269// FIXME: there are other cases where a type can be constrained by a concept,5270// e.g. inside `if constexpr(ConceptSpecializationExpr) { ... }`5271class ConceptInfo {5272public:5273// Describes a likely member of a type, inferred by concept constraints.5274// Offered as a code completion for T. T-> and T:: contexts.5275struct Member {5276// Always non-null: we only handle members with ordinary identifier names.5277const IdentifierInfo *Name = nullptr;5278// Set for functions we've seen called.5279// We don't have the declared parameter types, only the actual types of5280// arguments we've seen. These are still valuable, as it's hard to render5281// a useful function completion with neither parameter types nor names!5282std::optional<SmallVector<QualType, 1>> ArgTypes;5283// Whether this is accessed as T.member, T->member, or T::member.5284enum AccessOperator {5285Colons,5286Arrow,5287Dot,5288} Operator = Dot;5289// What's known about the type of a variable or return type of a function.5290const TypeConstraint *ResultType = nullptr;5291// FIXME: also track:5292// - kind of entity (function/variable/type), to expose structured results5293// - template args kinds/types, as a proxy for template params52945295// For now we simply return these results as "pattern" strings.5296CodeCompletionString *render(Sema &S, CodeCompletionAllocator &Alloc,5297CodeCompletionTUInfo &Info) const {5298CodeCompletionBuilder B(Alloc, Info);5299// Result type5300if (ResultType) {5301std::string AsString;5302{5303llvm::raw_string_ostream OS(AsString);5304QualType ExactType = deduceType(*ResultType);5305if (!ExactType.isNull())5306ExactType.print(OS, getCompletionPrintingPolicy(S));5307else5308ResultType->print(OS, getCompletionPrintingPolicy(S));5309}5310B.AddResultTypeChunk(Alloc.CopyString(AsString));5311}5312// Member name5313B.AddTypedTextChunk(Alloc.CopyString(Name->getName()));5314// Function argument list5315if (ArgTypes) {5316B.AddChunk(clang::CodeCompletionString::CK_LeftParen);5317bool First = true;5318for (QualType Arg : *ArgTypes) {5319if (First)5320First = false;5321else {5322B.AddChunk(clang::CodeCompletionString::CK_Comma);5323B.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);5324}5325B.AddPlaceholderChunk(Alloc.CopyString(5326Arg.getAsString(getCompletionPrintingPolicy(S))));5327}5328B.AddChunk(clang::CodeCompletionString::CK_RightParen);5329}5330return B.TakeString();5331}5332};53335334// BaseType is the type parameter T to infer members from.5335// T must be accessible within S, as we use it to find the template entity5336// that T is attached to in order to gather the relevant constraints.5337ConceptInfo(const TemplateTypeParmType &BaseType, Scope *S) {5338auto *TemplatedEntity = getTemplatedEntity(BaseType.getDecl(), S);5339for (const Expr *E : constraintsForTemplatedEntity(TemplatedEntity))5340believe(E, &BaseType);5341}53425343std::vector<Member> members() {5344std::vector<Member> Results;5345for (const auto &E : this->Results)5346Results.push_back(E.second);5347llvm::sort(Results, [](const Member &L, const Member &R) {5348return L.Name->getName() < R.Name->getName();5349});5350return Results;5351}53525353private:5354// Infer members of T, given that the expression E (dependent on T) is true.5355void believe(const Expr *E, const TemplateTypeParmType *T) {5356if (!E || !T)5357return;5358if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(E)) {5359// If the concept is5360// template <class A, class B> concept CD = f<A, B>();5361// And the concept specialization is5362// CD<int, T>5363// Then we're substituting T for B, so we want to make f<A, B>() true5364// by adding members to B - i.e. believe(f<A, B>(), B);5365//5366// For simplicity:5367// - we don't attempt to substitute int for A5368// - when T is used in other ways (like CD<T*>) we ignore it5369ConceptDecl *CD = CSE->getNamedConcept();5370TemplateParameterList *Params = CD->getTemplateParameters();5371unsigned Index = 0;5372for (const auto &Arg : CSE->getTemplateArguments()) {5373if (Index >= Params->size())5374break; // Won't happen in valid code.5375if (isApprox(Arg, T)) {5376auto *TTPD = dyn_cast<TemplateTypeParmDecl>(Params->getParam(Index));5377if (!TTPD)5378continue;5379// T was used as an argument, and bound to the parameter TT.5380auto *TT = cast<TemplateTypeParmType>(TTPD->getTypeForDecl());5381// So now we know the constraint as a function of TT is true.5382believe(CD->getConstraintExpr(), TT);5383// (concepts themselves have no associated constraints to require)5384}53855386++Index;5387}5388} else if (auto *BO = dyn_cast<BinaryOperator>(E)) {5389// For A && B, we can infer members from both branches.5390// For A || B, the union is still more useful than the intersection.5391if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {5392believe(BO->getLHS(), T);5393believe(BO->getRHS(), T);5394}5395} else if (auto *RE = dyn_cast<RequiresExpr>(E)) {5396// A requires(){...} lets us infer members from each requirement.5397for (const concepts::Requirement *Req : RE->getRequirements()) {5398if (!Req->isDependent())5399continue; // Can't tell us anything about T.5400// Now Req cannot a substitution-error: those aren't dependent.54015402if (auto *TR = dyn_cast<concepts::TypeRequirement>(Req)) {5403// Do a full traversal so we get `foo` from `typename T::foo::bar`.5404QualType AssertedType = TR->getType()->getType();5405ValidVisitor(this, T).TraverseType(AssertedType);5406} else if (auto *ER = dyn_cast<concepts::ExprRequirement>(Req)) {5407ValidVisitor Visitor(this, T);5408// If we have a type constraint on the value of the expression,5409// AND the whole outer expression describes a member, then we'll5410// be able to use the constraint to provide the return type.5411if (ER->getReturnTypeRequirement().isTypeConstraint()) {5412Visitor.OuterType =5413ER->getReturnTypeRequirement().getTypeConstraint();5414Visitor.OuterExpr = ER->getExpr();5415}5416Visitor.TraverseStmt(ER->getExpr());5417} else if (auto *NR = dyn_cast<concepts::NestedRequirement>(Req)) {5418believe(NR->getConstraintExpr(), T);5419}5420}5421}5422}54235424// This visitor infers members of T based on traversing expressions/types5425// that involve T. It is invoked with code known to be valid for T.5426class ValidVisitor : public RecursiveASTVisitor<ValidVisitor> {5427ConceptInfo *Outer;5428const TemplateTypeParmType *T;54295430CallExpr *Caller = nullptr;5431Expr *Callee = nullptr;54325433public:5434// If set, OuterExpr is constrained by OuterType.5435Expr *OuterExpr = nullptr;5436const TypeConstraint *OuterType = nullptr;54375438ValidVisitor(ConceptInfo *Outer, const TemplateTypeParmType *T)5439: Outer(Outer), T(T) {5440assert(T);5441}54425443// In T.foo or T->foo, `foo` is a member function/variable.5444bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {5445const Type *Base = E->getBaseType().getTypePtr();5446bool IsArrow = E->isArrow();5447if (Base->isPointerType() && IsArrow) {5448IsArrow = false;5449Base = Base->getPointeeType().getTypePtr();5450}5451if (isApprox(Base, T))5452addValue(E, E->getMember(), IsArrow ? Member::Arrow : Member::Dot);5453return true;5454}54555456// In T::foo, `foo` is a static member function/variable.5457bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {5458if (E->getQualifier() && isApprox(E->getQualifier()->getAsType(), T))5459addValue(E, E->getDeclName(), Member::Colons);5460return true;5461}54625463// In T::typename foo, `foo` is a type.5464bool VisitDependentNameType(DependentNameType *DNT) {5465const auto *Q = DNT->getQualifier();5466if (Q && isApprox(Q->getAsType(), T))5467addType(DNT->getIdentifier());5468return true;5469}54705471// In T::foo::bar, `foo` must be a type.5472// VisitNNS() doesn't exist, and TraverseNNS isn't always called :-(5473bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) {5474if (NNSL) {5475NestedNameSpecifier *NNS = NNSL.getNestedNameSpecifier();5476const auto *Q = NNS->getPrefix();5477if (Q && isApprox(Q->getAsType(), T))5478addType(NNS->getAsIdentifier());5479}5480// FIXME: also handle T::foo<X>::bar5481return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL);5482}54835484// FIXME also handle T::foo<X>54855486// Track the innermost caller/callee relationship so we can tell if a5487// nested expr is being called as a function.5488bool VisitCallExpr(CallExpr *CE) {5489Caller = CE;5490Callee = CE->getCallee();5491return true;5492}54935494private:5495void addResult(Member &&M) {5496auto R = Outer->Results.try_emplace(M.Name);5497Member &O = R.first->second;5498// Overwrite existing if the new member has more info.5499// The preference of . vs :: vs -> is fairly arbitrary.5500if (/*Inserted*/ R.second ||5501std::make_tuple(M.ArgTypes.has_value(), M.ResultType != nullptr,5502M.Operator) > std::make_tuple(O.ArgTypes.has_value(),5503O.ResultType != nullptr,5504O.Operator))5505O = std::move(M);5506}55075508void addType(const IdentifierInfo *Name) {5509if (!Name)5510return;5511Member M;5512M.Name = Name;5513M.Operator = Member::Colons;5514addResult(std::move(M));5515}55165517void addValue(Expr *E, DeclarationName Name,5518Member::AccessOperator Operator) {5519if (!Name.isIdentifier())5520return;5521Member Result;5522Result.Name = Name.getAsIdentifierInfo();5523Result.Operator = Operator;5524// If this is the callee of an immediately-enclosing CallExpr, then5525// treat it as a method, otherwise it's a variable.5526if (Caller != nullptr && Callee == E) {5527Result.ArgTypes.emplace();5528for (const auto *Arg : Caller->arguments())5529Result.ArgTypes->push_back(Arg->getType());5530if (Caller == OuterExpr) {5531Result.ResultType = OuterType;5532}5533} else {5534if (E == OuterExpr)5535Result.ResultType = OuterType;5536}5537addResult(std::move(Result));5538}5539};55405541static bool isApprox(const TemplateArgument &Arg, const Type *T) {5542return Arg.getKind() == TemplateArgument::Type &&5543isApprox(Arg.getAsType().getTypePtr(), T);5544}55455546static bool isApprox(const Type *T1, const Type *T2) {5547return T1 && T2 &&5548T1->getCanonicalTypeUnqualified() ==5549T2->getCanonicalTypeUnqualified();5550}55515552// Returns the DeclContext immediately enclosed by the template parameter5553// scope. For primary templates, this is the templated (e.g.) CXXRecordDecl.5554// For specializations, this is e.g. ClassTemplatePartialSpecializationDecl.5555static DeclContext *getTemplatedEntity(const TemplateTypeParmDecl *D,5556Scope *S) {5557if (D == nullptr)5558return nullptr;5559Scope *Inner = nullptr;5560while (S) {5561if (S->isTemplateParamScope() && S->isDeclScope(D))5562return Inner ? Inner->getEntity() : nullptr;5563Inner = S;5564S = S->getParent();5565}5566return nullptr;5567}55685569// Gets all the type constraint expressions that might apply to the type5570// variables associated with DC (as returned by getTemplatedEntity()).5571static SmallVector<const Expr *, 1>5572constraintsForTemplatedEntity(DeclContext *DC) {5573SmallVector<const Expr *, 1> Result;5574if (DC == nullptr)5575return Result;5576// Primary templates can have constraints.5577if (const auto *TD = cast<Decl>(DC)->getDescribedTemplate())5578TD->getAssociatedConstraints(Result);5579// Partial specializations may have constraints.5580if (const auto *CTPSD =5581dyn_cast<ClassTemplatePartialSpecializationDecl>(DC))5582CTPSD->getAssociatedConstraints(Result);5583if (const auto *VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl>(DC))5584VTPSD->getAssociatedConstraints(Result);5585return Result;5586}55875588// Attempt to find the unique type satisfying a constraint.5589// This lets us show e.g. `int` instead of `std::same_as<int>`.5590static QualType deduceType(const TypeConstraint &T) {5591// Assume a same_as<T> return type constraint is std::same_as or equivalent.5592// In this case the return type is T.5593DeclarationName DN = T.getNamedConcept()->getDeclName();5594if (DN.isIdentifier() && DN.getAsIdentifierInfo()->isStr("same_as"))5595if (const auto *Args = T.getTemplateArgsAsWritten())5596if (Args->getNumTemplateArgs() == 1) {5597const auto &Arg = Args->arguments().front().getArgument();5598if (Arg.getKind() == TemplateArgument::Type)5599return Arg.getAsType();5600}5601return {};5602}56035604llvm::DenseMap<const IdentifierInfo *, Member> Results;5605};56065607// Returns a type for E that yields acceptable member completions.5608// In particular, when E->getType() is DependentTy, try to guess a likely type.5609// We accept some lossiness (like dropping parameters).5610// We only try to handle common expressions on the LHS of MemberExpr.5611QualType getApproximateType(const Expr *E) {5612if (E->getType().isNull())5613return QualType();5614E = E->IgnoreParenImpCasts();5615QualType Unresolved = E->getType();5616// We only resolve DependentTy, or undeduced autos (including auto* etc).5617if (!Unresolved->isSpecificBuiltinType(BuiltinType::Dependent)) {5618AutoType *Auto = Unresolved->getContainedAutoType();5619if (!Auto || !Auto->isUndeducedAutoType())5620return Unresolved;5621}5622// A call: approximate-resolve callee to a function type, get its return type5623if (const CallExpr *CE = llvm::dyn_cast<CallExpr>(E)) {5624QualType Callee = getApproximateType(CE->getCallee());5625if (Callee.isNull() ||5626Callee->isSpecificPlaceholderType(BuiltinType::BoundMember))5627Callee = Expr::findBoundMemberType(CE->getCallee());5628if (Callee.isNull())5629return Unresolved;56305631if (const auto *FnTypePtr = Callee->getAs<PointerType>()) {5632Callee = FnTypePtr->getPointeeType();5633} else if (const auto *BPT = Callee->getAs<BlockPointerType>()) {5634Callee = BPT->getPointeeType();5635}5636if (const FunctionType *FnType = Callee->getAs<FunctionType>())5637return FnType->getReturnType().getNonReferenceType();56385639// Unresolved call: try to guess the return type.5640if (const auto *OE = llvm::dyn_cast<OverloadExpr>(CE->getCallee())) {5641// If all candidates have the same approximate return type, use it.5642// Discard references and const to allow more to be "the same".5643// (In particular, if there's one candidate + ADL, resolve it).5644const Type *Common = nullptr;5645for (const auto *D : OE->decls()) {5646QualType ReturnType;5647if (const auto *FD = llvm::dyn_cast<FunctionDecl>(D))5648ReturnType = FD->getReturnType();5649else if (const auto *FTD = llvm::dyn_cast<FunctionTemplateDecl>(D))5650ReturnType = FTD->getTemplatedDecl()->getReturnType();5651if (ReturnType.isNull())5652continue;5653const Type *Candidate =5654ReturnType.getNonReferenceType().getCanonicalType().getTypePtr();5655if (Common && Common != Candidate)5656return Unresolved; // Multiple candidates.5657Common = Candidate;5658}5659if (Common != nullptr)5660return QualType(Common, 0);5661}5662}5663// A dependent member: approximate-resolve the base, then lookup.5664if (const auto *CDSME = llvm::dyn_cast<CXXDependentScopeMemberExpr>(E)) {5665QualType Base = CDSME->isImplicitAccess()5666? CDSME->getBaseType()5667: getApproximateType(CDSME->getBase());5668if (CDSME->isArrow() && !Base.isNull())5669Base = Base->getPointeeType(); // could handle unique_ptr etc here?5670auto *RD =5671Base.isNull()5672? nullptr5673: llvm::dyn_cast_or_null<CXXRecordDecl>(getAsRecordDecl(Base));5674if (RD && RD->isCompleteDefinition()) {5675// Look up member heuristically, including in bases.5676for (const auto *Member : RD->lookupDependentName(5677CDSME->getMember(), [](const NamedDecl *Member) {5678return llvm::isa<ValueDecl>(Member);5679})) {5680return llvm::cast<ValueDecl>(Member)->getType().getNonReferenceType();5681}5682}5683}5684// A reference to an `auto` variable: approximate-resolve its initializer.5685if (const auto *DRE = llvm::dyn_cast<DeclRefExpr>(E)) {5686if (const auto *VD = llvm::dyn_cast<VarDecl>(DRE->getDecl())) {5687if (VD->hasInit())5688return getApproximateType(VD->getInit());5689}5690}5691if (const auto *UO = llvm::dyn_cast<UnaryOperator>(E)) {5692if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) {5693// We recurse into the subexpression because it could be of dependent5694// type.5695if (auto Pointee = getApproximateType(UO->getSubExpr())->getPointeeType();5696!Pointee.isNull())5697return Pointee;5698// Our caller expects a non-null result, even though the SubType is5699// supposed to have a pointee. Fall through to Unresolved anyway.5700}5701}5702return Unresolved;5703}57045705// If \p Base is ParenListExpr, assume a chain of comma operators and pick the5706// last expr. We expect other ParenListExprs to be resolved to e.g. constructor5707// calls before here. (So the ParenListExpr should be nonempty, but check just5708// in case)5709Expr *unwrapParenList(Expr *Base) {5710if (auto *PLE = llvm::dyn_cast_or_null<ParenListExpr>(Base)) {5711if (PLE->getNumExprs() == 0)5712return nullptr;5713Base = PLE->getExpr(PLE->getNumExprs() - 1);5714}5715return Base;5716}57175718} // namespace57195720void SemaCodeCompletion::CodeCompleteMemberReferenceExpr(5721Scope *S, Expr *Base, Expr *OtherOpBase, SourceLocation OpLoc, bool IsArrow,5722bool IsBaseExprStatement, QualType PreferredType) {5723Base = unwrapParenList(Base);5724OtherOpBase = unwrapParenList(OtherOpBase);5725if (!Base || !CodeCompleter)5726return;57275728ExprResult ConvertedBase =5729SemaRef.PerformMemberExprBaseConversion(Base, IsArrow);5730if (ConvertedBase.isInvalid())5731return;5732QualType ConvertedBaseType = getApproximateType(ConvertedBase.get());57335734enum CodeCompletionContext::Kind contextKind;57355736if (IsArrow) {5737if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())5738ConvertedBaseType = Ptr->getPointeeType();5739}57405741if (IsArrow) {5742contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;5743} else {5744if (ConvertedBaseType->isObjCObjectPointerType() ||5745ConvertedBaseType->isObjCObjectOrInterfaceType()) {5746contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;5747} else {5748contextKind = CodeCompletionContext::CCC_DotMemberAccess;5749}5750}57515752CodeCompletionContext CCContext(contextKind, ConvertedBaseType);5753CCContext.setPreferredType(PreferredType);5754ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),5755CodeCompleter->getCodeCompletionTUInfo(), CCContext,5756&ResultBuilder::IsMember);57575758auto DoCompletion = [&](Expr *Base, bool IsArrow,5759std::optional<FixItHint> AccessOpFixIt) -> bool {5760if (!Base)5761return false;57625763ExprResult ConvertedBase =5764SemaRef.PerformMemberExprBaseConversion(Base, IsArrow);5765if (ConvertedBase.isInvalid())5766return false;5767Base = ConvertedBase.get();57685769QualType BaseType = getApproximateType(Base);5770if (BaseType.isNull())5771return false;5772ExprValueKind BaseKind = Base->getValueKind();57735774if (IsArrow) {5775if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {5776BaseType = Ptr->getPointeeType();5777BaseKind = VK_LValue;5778} else if (BaseType->isObjCObjectPointerType() ||5779BaseType->isTemplateTypeParmType()) {5780// Both cases (dot/arrow) handled below.5781} else {5782return false;5783}5784}57855786if (RecordDecl *RD = getAsRecordDecl(BaseType)) {5787AddRecordMembersCompletionResults(SemaRef, Results, S, BaseType, BaseKind,5788RD, std::move(AccessOpFixIt));5789} else if (const auto *TTPT =5790dyn_cast<TemplateTypeParmType>(BaseType.getTypePtr())) {5791auto Operator =5792IsArrow ? ConceptInfo::Member::Arrow : ConceptInfo::Member::Dot;5793for (const auto &R : ConceptInfo(*TTPT, S).members()) {5794if (R.Operator != Operator)5795continue;5796CodeCompletionResult Result(5797R.render(SemaRef, CodeCompleter->getAllocator(),5798CodeCompleter->getCodeCompletionTUInfo()));5799if (AccessOpFixIt)5800Result.FixIts.push_back(*AccessOpFixIt);5801Results.AddResult(std::move(Result));5802}5803} else if (!IsArrow && BaseType->isObjCObjectPointerType()) {5804// Objective-C property reference. Bail if we're performing fix-it code5805// completion since Objective-C properties are normally backed by ivars,5806// most Objective-C fix-its here would have little value.5807if (AccessOpFixIt) {5808return false;5809}5810AddedPropertiesSet AddedProperties;58115812if (const ObjCObjectPointerType *ObjCPtr =5813BaseType->getAsObjCInterfacePointerType()) {5814// Add property results based on our interface.5815assert(ObjCPtr && "Non-NULL pointer guaranteed above!");5816AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,5817/*AllowNullaryMethods=*/true, SemaRef.CurContext,5818AddedProperties, Results, IsBaseExprStatement);5819}58205821// Add properties from the protocols in a qualified interface.5822for (auto *I : BaseType->castAs<ObjCObjectPointerType>()->quals())5823AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,5824SemaRef.CurContext, AddedProperties, Results,5825IsBaseExprStatement, /*IsClassProperty*/ false,5826/*InOriginalClass*/ false);5827} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||5828(!IsArrow && BaseType->isObjCObjectType())) {5829// Objective-C instance variable access. Bail if we're performing fix-it5830// code completion since Objective-C properties are normally backed by5831// ivars, most Objective-C fix-its here would have little value.5832if (AccessOpFixIt) {5833return false;5834}5835ObjCInterfaceDecl *Class = nullptr;5836if (const ObjCObjectPointerType *ObjCPtr =5837BaseType->getAs<ObjCObjectPointerType>())5838Class = ObjCPtr->getInterfaceDecl();5839else5840Class = BaseType->castAs<ObjCObjectType>()->getInterface();58415842// Add all ivars from this class and its superclasses.5843if (Class) {5844CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);5845Results.setFilter(&ResultBuilder::IsObjCIvar);5846SemaRef.LookupVisibleDecls(Class, Sema::LookupMemberName, Consumer,5847CodeCompleter->includeGlobals(),5848/*IncludeDependentBases=*/false,5849CodeCompleter->loadExternal());5850}5851}58525853// FIXME: How do we cope with isa?5854return true;5855};58565857Results.EnterNewScope();58585859bool CompletionSucceded = DoCompletion(Base, IsArrow, std::nullopt);5860if (CodeCompleter->includeFixIts()) {5861const CharSourceRange OpRange =5862CharSourceRange::getTokenRange(OpLoc, OpLoc);5863CompletionSucceded |= DoCompletion(5864OtherOpBase, !IsArrow,5865FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));5866}58675868Results.ExitScope();58695870if (!CompletionSucceded)5871return;58725873// Hand off the results found for code completion.5874HandleCodeCompleteResults(&SemaRef, CodeCompleter,5875Results.getCompletionContext(), Results.data(),5876Results.size());5877}58785879void SemaCodeCompletion::CodeCompleteObjCClassPropertyRefExpr(5880Scope *S, const IdentifierInfo &ClassName, SourceLocation ClassNameLoc,5881bool IsBaseExprStatement) {5882const IdentifierInfo *ClassNamePtr = &ClassName;5883ObjCInterfaceDecl *IFace =5884SemaRef.ObjC().getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);5885if (!IFace)5886return;5887CodeCompletionContext CCContext(5888CodeCompletionContext::CCC_ObjCPropertyAccess);5889ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),5890CodeCompleter->getCodeCompletionTUInfo(), CCContext,5891&ResultBuilder::IsMember);5892Results.EnterNewScope();5893AddedPropertiesSet AddedProperties;5894AddObjCProperties(CCContext, IFace, true,5895/*AllowNullaryMethods=*/true, SemaRef.CurContext,5896AddedProperties, Results, IsBaseExprStatement,5897/*IsClassProperty=*/true);5898Results.ExitScope();5899HandleCodeCompleteResults(&SemaRef, CodeCompleter,5900Results.getCompletionContext(), Results.data(),5901Results.size());5902}59035904void SemaCodeCompletion::CodeCompleteTag(Scope *S, unsigned TagSpec) {5905if (!CodeCompleter)5906return;59075908ResultBuilder::LookupFilter Filter = nullptr;5909enum CodeCompletionContext::Kind ContextKind =5910CodeCompletionContext::CCC_Other;5911switch ((DeclSpec::TST)TagSpec) {5912case DeclSpec::TST_enum:5913Filter = &ResultBuilder::IsEnum;5914ContextKind = CodeCompletionContext::CCC_EnumTag;5915break;59165917case DeclSpec::TST_union:5918Filter = &ResultBuilder::IsUnion;5919ContextKind = CodeCompletionContext::CCC_UnionTag;5920break;59215922case DeclSpec::TST_struct:5923case DeclSpec::TST_class:5924case DeclSpec::TST_interface:5925Filter = &ResultBuilder::IsClassOrStruct;5926ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;5927break;59285929default:5930llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");5931}59325933ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),5934CodeCompleter->getCodeCompletionTUInfo(), ContextKind);5935CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);59365937// First pass: look for tags.5938Results.setFilter(Filter);5939SemaRef.LookupVisibleDecls(S, Sema::LookupTagName, Consumer,5940CodeCompleter->includeGlobals(),5941CodeCompleter->loadExternal());59425943if (CodeCompleter->includeGlobals()) {5944// Second pass: look for nested name specifiers.5945Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);5946SemaRef.LookupVisibleDecls(S, Sema::LookupNestedNameSpecifierName, Consumer,5947CodeCompleter->includeGlobals(),5948CodeCompleter->loadExternal());5949}59505951HandleCodeCompleteResults(&SemaRef, CodeCompleter,5952Results.getCompletionContext(), Results.data(),5953Results.size());5954}59555956static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,5957const LangOptions &LangOpts) {5958if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))5959Results.AddResult("const");5960if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))5961Results.AddResult("volatile");5962if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))5963Results.AddResult("restrict");5964if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))5965Results.AddResult("_Atomic");5966if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))5967Results.AddResult("__unaligned");5968}59695970void SemaCodeCompletion::CodeCompleteTypeQualifiers(DeclSpec &DS) {5971ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),5972CodeCompleter->getCodeCompletionTUInfo(),5973CodeCompletionContext::CCC_TypeQualifiers);5974Results.EnterNewScope();5975AddTypeQualifierResults(DS, Results, getLangOpts());5976Results.ExitScope();5977HandleCodeCompleteResults(&SemaRef, CodeCompleter,5978Results.getCompletionContext(), Results.data(),5979Results.size());5980}59815982void SemaCodeCompletion::CodeCompleteFunctionQualifiers(5983DeclSpec &DS, Declarator &D, const VirtSpecifiers *VS) {5984ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),5985CodeCompleter->getCodeCompletionTUInfo(),5986CodeCompletionContext::CCC_TypeQualifiers);5987Results.EnterNewScope();5988AddTypeQualifierResults(DS, Results, getLangOpts());5989if (getLangOpts().CPlusPlus11) {5990Results.AddResult("noexcept");5991if (D.getContext() == DeclaratorContext::Member && !D.isCtorOrDtor() &&5992!D.isStaticMember()) {5993if (!VS || !VS->isFinalSpecified())5994Results.AddResult("final");5995if (!VS || !VS->isOverrideSpecified())5996Results.AddResult("override");5997}5998}5999Results.ExitScope();6000HandleCodeCompleteResults(&SemaRef, CodeCompleter,6001Results.getCompletionContext(), Results.data(),6002Results.size());6003}60046005void SemaCodeCompletion::CodeCompleteBracketDeclarator(Scope *S) {6006CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));6007}60086009void SemaCodeCompletion::CodeCompleteCase(Scope *S) {6010if (SemaRef.getCurFunction()->SwitchStack.empty() || !CodeCompleter)6011return;60126013SwitchStmt *Switch =6014SemaRef.getCurFunction()->SwitchStack.back().getPointer();6015// Condition expression might be invalid, do not continue in this case.6016if (!Switch->getCond())6017return;6018QualType type = Switch->getCond()->IgnoreImplicit()->getType();6019if (!type->isEnumeralType()) {6020CodeCompleteExpressionData Data(type);6021Data.IntegralConstantExpression = true;6022CodeCompleteExpression(S, Data);6023return;6024}60256026// Code-complete the cases of a switch statement over an enumeration type6027// by providing the list of6028EnumDecl *Enum = type->castAs<EnumType>()->getDecl();6029if (EnumDecl *Def = Enum->getDefinition())6030Enum = Def;60316032// Determine which enumerators we have already seen in the switch statement.6033// FIXME: Ideally, we would also be able to look *past* the code-completion6034// token, in case we are code-completing in the middle of the switch and not6035// at the end. However, we aren't able to do so at the moment.6036CoveredEnumerators Enumerators;6037for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;6038SC = SC->getNextSwitchCase()) {6039CaseStmt *Case = dyn_cast<CaseStmt>(SC);6040if (!Case)6041continue;60426043Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();6044if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))6045if (auto *Enumerator =6046dyn_cast<EnumConstantDecl>(DRE->getDecl())) {6047// We look into the AST of the case statement to determine which6048// enumerator was named. Alternatively, we could compute the value of6049// the integral constant expression, then compare it against the6050// values of each enumerator. However, value-based approach would not6051// work as well with C++ templates where enumerators declared within a6052// template are type- and value-dependent.6053Enumerators.Seen.insert(Enumerator);60546055// If this is a qualified-id, keep track of the nested-name-specifier6056// so that we can reproduce it as part of code completion, e.g.,6057//6058// switch (TagD.getKind()) {6059// case TagDecl::TK_enum:6060// break;6061// case XXX6062//6063// At the XXX, our completions are TagDecl::TK_union,6064// TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,6065// TK_struct, and TK_class.6066Enumerators.SuggestedQualifier = DRE->getQualifier();6067}6068}60696070// Add any enumerators that have not yet been mentioned.6071ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6072CodeCompleter->getCodeCompletionTUInfo(),6073CodeCompletionContext::CCC_Expression);6074AddEnumerators(Results, getASTContext(), Enum, SemaRef.CurContext,6075Enumerators);60766077if (CodeCompleter->includeMacros()) {6078AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false);6079}6080HandleCodeCompleteResults(&SemaRef, CodeCompleter,6081Results.getCompletionContext(), Results.data(),6082Results.size());6083}60846085static bool anyNullArguments(ArrayRef<Expr *> Args) {6086if (Args.size() && !Args.data())6087return true;60886089for (unsigned I = 0; I != Args.size(); ++I)6090if (!Args[I])6091return true;60926093return false;6094}60956096typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;60976098static void mergeCandidatesWithResults(6099Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,6100OverloadCandidateSet &CandidateSet, SourceLocation Loc, size_t ArgSize) {6101// Sort the overload candidate set by placing the best overloads first.6102llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,6103const OverloadCandidate &Y) {6104return isBetterOverloadCandidate(SemaRef, X, Y, Loc,6105CandidateSet.getKind());6106});61076108// Add the remaining viable overload candidates as code-completion results.6109for (OverloadCandidate &Candidate : CandidateSet) {6110if (Candidate.Function) {6111if (Candidate.Function->isDeleted())6112continue;6113if (shouldEnforceArgLimit(/*PartialOverloading=*/true,6114Candidate.Function) &&6115Candidate.Function->getNumParams() <= ArgSize &&6116// Having zero args is annoying, normally we don't surface a function6117// with 2 params, if you already have 2 params, because you are6118// inserting the 3rd now. But with zero, it helps the user to figure6119// out there are no overloads that take any arguments. Hence we are6120// keeping the overload.6121ArgSize > 0)6122continue;6123}6124if (Candidate.Viable)6125Results.push_back(ResultCandidate(Candidate.Function));6126}6127}61286129/// Get the type of the Nth parameter from a given set of overload6130/// candidates.6131static QualType getParamType(Sema &SemaRef,6132ArrayRef<ResultCandidate> Candidates, unsigned N) {61336134// Given the overloads 'Candidates' for a function call matching all arguments6135// up to N, return the type of the Nth parameter if it is the same for all6136// overload candidates.6137QualType ParamType;6138for (auto &Candidate : Candidates) {6139QualType CandidateParamType = Candidate.getParamType(N);6140if (CandidateParamType.isNull())6141continue;6142if (ParamType.isNull()) {6143ParamType = CandidateParamType;6144continue;6145}6146if (!SemaRef.Context.hasSameUnqualifiedType(6147ParamType.getNonReferenceType(),6148CandidateParamType.getNonReferenceType()))6149// Two conflicting types, give up.6150return QualType();6151}61526153return ParamType;6154}61556156static QualType6157ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef<ResultCandidate> Candidates,6158unsigned CurrentArg, SourceLocation OpenParLoc,6159bool Braced) {6160if (Candidates.empty())6161return QualType();6162if (SemaRef.getPreprocessor().isCodeCompletionReached())6163SemaRef.CodeCompletion().CodeCompleter->ProcessOverloadCandidates(6164SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc,6165Braced);6166return getParamType(SemaRef, Candidates, CurrentArg);6167}61686169// Given a callee expression `Fn`, if the call is through a function pointer,6170// try to find the declaration of the corresponding function pointer type,6171// so that we can recover argument names from it.6172static FunctionProtoTypeLoc GetPrototypeLoc(Expr *Fn) {6173TypeLoc Target;61746175if (const auto *T = Fn->getType().getTypePtr()->getAs<TypedefType>()) {6176Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();61776178} else if (const auto *DR = dyn_cast<DeclRefExpr>(Fn)) {6179const auto *D = DR->getDecl();6180if (const auto *const VD = dyn_cast<VarDecl>(D)) {6181Target = VD->getTypeSourceInfo()->getTypeLoc();6182}6183} else if (const auto *ME = dyn_cast<MemberExpr>(Fn)) {6184const auto *MD = ME->getMemberDecl();6185if (const auto *FD = dyn_cast<FieldDecl>(MD)) {6186Target = FD->getTypeSourceInfo()->getTypeLoc();6187}6188}61896190if (!Target)6191return {};61926193// Unwrap types that may be wrapping the function type6194while (true) {6195if (auto P = Target.getAs<PointerTypeLoc>()) {6196Target = P.getPointeeLoc();6197continue;6198}6199if (auto A = Target.getAs<AttributedTypeLoc>()) {6200Target = A.getModifiedLoc();6201continue;6202}6203if (auto P = Target.getAs<ParenTypeLoc>()) {6204Target = P.getInnerLoc();6205continue;6206}6207break;6208}62096210if (auto F = Target.getAs<FunctionProtoTypeLoc>()) {6211return F;6212}62136214return {};6215}62166217QualType6218SemaCodeCompletion::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,6219SourceLocation OpenParLoc) {6220Fn = unwrapParenList(Fn);6221if (!CodeCompleter || !Fn)6222return QualType();62236224// FIXME: Provide support for variadic template functions.6225// Ignore type-dependent call expressions entirely.6226if (Fn->isTypeDependent() || anyNullArguments(Args))6227return QualType();6228// In presence of dependent args we surface all possible signatures using the6229// non-dependent args in the prefix. Afterwards we do a post filtering to make6230// sure provided candidates satisfy parameter count restrictions.6231auto ArgsWithoutDependentTypes =6232Args.take_while([](Expr *Arg) { return !Arg->isTypeDependent(); });62336234SmallVector<ResultCandidate, 8> Results;62356236Expr *NakedFn = Fn->IgnoreParenCasts();6237// Build an overload candidate set based on the functions we find.6238SourceLocation Loc = Fn->getExprLoc();6239OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);62406241if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) {6242SemaRef.AddOverloadedCallCandidates(ULE, ArgsWithoutDependentTypes,6243CandidateSet,6244/*PartialOverloading=*/true);6245} else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {6246TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;6247if (UME->hasExplicitTemplateArgs()) {6248UME->copyTemplateArgumentsInto(TemplateArgsBuffer);6249TemplateArgs = &TemplateArgsBuffer;6250}62516252// Add the base as first argument (use a nullptr if the base is implicit).6253SmallVector<Expr *, 12> ArgExprs(62541, UME->isImplicitAccess() ? nullptr : UME->getBase());6255ArgExprs.append(ArgsWithoutDependentTypes.begin(),6256ArgsWithoutDependentTypes.end());6257UnresolvedSet<8> Decls;6258Decls.append(UME->decls_begin(), UME->decls_end());6259const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();6260SemaRef.AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,6261/*SuppressUserConversions=*/false,6262/*PartialOverloading=*/true,6263FirstArgumentIsBase);6264} else {6265FunctionDecl *FD = nullptr;6266if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))6267FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());6268else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))6269FD = dyn_cast<FunctionDecl>(DRE->getDecl());6270if (FD) { // We check whether it's a resolved function declaration.6271if (!getLangOpts().CPlusPlus ||6272!FD->getType()->getAs<FunctionProtoType>())6273Results.push_back(ResultCandidate(FD));6274else6275SemaRef.AddOverloadCandidate(FD,6276DeclAccessPair::make(FD, FD->getAccess()),6277ArgsWithoutDependentTypes, CandidateSet,6278/*SuppressUserConversions=*/false,6279/*PartialOverloading=*/true);62806281} else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {6282// If expression's type is CXXRecordDecl, it may overload the function6283// call operator, so we check if it does and add them as candidates.6284// A complete type is needed to lookup for member function call operators.6285if (SemaRef.isCompleteType(Loc, NakedFn->getType())) {6286DeclarationName OpName =6287getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);6288LookupResult R(SemaRef, OpName, Loc, Sema::LookupOrdinaryName);6289SemaRef.LookupQualifiedName(R, DC);6290R.suppressDiagnostics();6291SmallVector<Expr *, 12> ArgExprs(1, NakedFn);6292ArgExprs.append(ArgsWithoutDependentTypes.begin(),6293ArgsWithoutDependentTypes.end());6294SemaRef.AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs,6295CandidateSet,6296/*ExplicitArgs=*/nullptr,6297/*SuppressUserConversions=*/false,6298/*PartialOverloading=*/true);6299}6300} else {6301// Lastly we check whether expression's type is function pointer or6302// function.63036304FunctionProtoTypeLoc P = GetPrototypeLoc(NakedFn);6305QualType T = NakedFn->getType();6306if (!T->getPointeeType().isNull())6307T = T->getPointeeType();63086309if (auto FP = T->getAs<FunctionProtoType>()) {6310if (!SemaRef.TooManyArguments(FP->getNumParams(),6311ArgsWithoutDependentTypes.size(),6312/*PartialOverloading=*/true) ||6313FP->isVariadic()) {6314if (P) {6315Results.push_back(ResultCandidate(P));6316} else {6317Results.push_back(ResultCandidate(FP));6318}6319}6320} else if (auto FT = T->getAs<FunctionType>())6321// No prototype and declaration, it may be a K & R style function.6322Results.push_back(ResultCandidate(FT));6323}6324}6325mergeCandidatesWithResults(SemaRef, Results, CandidateSet, Loc, Args.size());6326QualType ParamType = ProduceSignatureHelp(SemaRef, Results, Args.size(),6327OpenParLoc, /*Braced=*/false);6328return !CandidateSet.empty() ? ParamType : QualType();6329}63306331// Determine which param to continue aggregate initialization from after6332// a designated initializer.6333//6334// Given struct S { int a,b,c,d,e; }:6335// after `S{.b=1,` we want to suggest c to continue6336// after `S{.b=1, 2,` we continue with d (this is legal C and ext in C++)6337// after `S{.b=1, .a=2,` we continue with b (this is legal C and ext in C++)6338//6339// Possible outcomes:6340// - we saw a designator for a field, and continue from the returned index.6341// Only aggregate initialization is allowed.6342// - we saw a designator, but it was complex or we couldn't find the field.6343// Only aggregate initialization is possible, but we can't assist with it.6344// Returns an out-of-range index.6345// - we saw no designators, just positional arguments.6346// Returns std::nullopt.6347static std::optional<unsigned>6348getNextAggregateIndexAfterDesignatedInit(const ResultCandidate &Aggregate,6349ArrayRef<Expr *> Args) {6350static constexpr unsigned Invalid = std::numeric_limits<unsigned>::max();6351assert(Aggregate.getKind() == ResultCandidate::CK_Aggregate);63526353// Look for designated initializers.6354// They're in their syntactic form, not yet resolved to fields.6355const IdentifierInfo *DesignatedFieldName = nullptr;6356unsigned ArgsAfterDesignator = 0;6357for (const Expr *Arg : Args) {6358if (const auto *DIE = dyn_cast<DesignatedInitExpr>(Arg)) {6359if (DIE->size() == 1 && DIE->getDesignator(0)->isFieldDesignator()) {6360DesignatedFieldName = DIE->getDesignator(0)->getFieldName();6361ArgsAfterDesignator = 0;6362} else {6363return Invalid; // Complicated designator.6364}6365} else if (isa<DesignatedInitUpdateExpr>(Arg)) {6366return Invalid; // Unsupported.6367} else {6368++ArgsAfterDesignator;6369}6370}6371if (!DesignatedFieldName)6372return std::nullopt;63736374// Find the index within the class's fields.6375// (Probing getParamDecl() directly would be quadratic in number of fields).6376unsigned DesignatedIndex = 0;6377const FieldDecl *DesignatedField = nullptr;6378for (const auto *Field : Aggregate.getAggregate()->fields()) {6379if (Field->getIdentifier() == DesignatedFieldName) {6380DesignatedField = Field;6381break;6382}6383++DesignatedIndex;6384}6385if (!DesignatedField)6386return Invalid; // Designator referred to a missing field, give up.63876388// Find the index within the aggregate (which may have leading bases).6389unsigned AggregateSize = Aggregate.getNumParams();6390while (DesignatedIndex < AggregateSize &&6391Aggregate.getParamDecl(DesignatedIndex) != DesignatedField)6392++DesignatedIndex;63936394// Continue from the index after the last named field.6395return DesignatedIndex + ArgsAfterDesignator + 1;6396}63976398QualType SemaCodeCompletion::ProduceConstructorSignatureHelp(6399QualType Type, SourceLocation Loc, ArrayRef<Expr *> Args,6400SourceLocation OpenParLoc, bool Braced) {6401if (!CodeCompleter)6402return QualType();6403SmallVector<ResultCandidate, 8> Results;64046405// A complete type is needed to lookup for constructors.6406RecordDecl *RD =6407SemaRef.isCompleteType(Loc, Type) ? Type->getAsRecordDecl() : nullptr;6408if (!RD)6409return Type;6410CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD);64116412// Consider aggregate initialization.6413// We don't check that types so far are correct.6414// We also don't handle C99/C++17 brace-elision, we assume init-list elements6415// are 1:1 with fields.6416// FIXME: it would be nice to support "unwrapping" aggregates that contain6417// a single subaggregate, like std::array<T, N> -> T __elements[N].6418if (Braced && !RD->isUnion() &&6419(!getLangOpts().CPlusPlus || (CRD && CRD->isAggregate()))) {6420ResultCandidate AggregateSig(RD);6421unsigned AggregateSize = AggregateSig.getNumParams();64226423if (auto NextIndex =6424getNextAggregateIndexAfterDesignatedInit(AggregateSig, Args)) {6425// A designator was used, only aggregate init is possible.6426if (*NextIndex >= AggregateSize)6427return Type;6428Results.push_back(AggregateSig);6429return ProduceSignatureHelp(SemaRef, Results, *NextIndex, OpenParLoc,6430Braced);6431}64326433// Describe aggregate initialization, but also constructors below.6434if (Args.size() < AggregateSize)6435Results.push_back(AggregateSig);6436}64376438// FIXME: Provide support for member initializers.6439// FIXME: Provide support for variadic template constructors.64406441if (CRD) {6442OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);6443for (NamedDecl *C : SemaRef.LookupConstructors(CRD)) {6444if (auto *FD = dyn_cast<FunctionDecl>(C)) {6445// FIXME: we can't yet provide correct signature help for initializer6446// list constructors, so skip them entirely.6447if (Braced && getLangOpts().CPlusPlus &&6448SemaRef.isInitListConstructor(FD))6449continue;6450SemaRef.AddOverloadCandidate(6451FD, DeclAccessPair::make(FD, C->getAccess()), Args, CandidateSet,6452/*SuppressUserConversions=*/false,6453/*PartialOverloading=*/true,6454/*AllowExplicit*/ true);6455} else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {6456if (Braced && getLangOpts().CPlusPlus &&6457SemaRef.isInitListConstructor(FTD->getTemplatedDecl()))6458continue;64596460SemaRef.AddTemplateOverloadCandidate(6461FTD, DeclAccessPair::make(FTD, C->getAccess()),6462/*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,6463/*SuppressUserConversions=*/false,6464/*PartialOverloading=*/true);6465}6466}6467mergeCandidatesWithResults(SemaRef, Results, CandidateSet, Loc,6468Args.size());6469}64706471return ProduceSignatureHelp(SemaRef, Results, Args.size(), OpenParLoc,6472Braced);6473}64746475QualType SemaCodeCompletion::ProduceCtorInitMemberSignatureHelp(6476Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,6477ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc,6478bool Braced) {6479if (!CodeCompleter)6480return QualType();64816482CXXConstructorDecl *Constructor =6483dyn_cast<CXXConstructorDecl>(ConstructorDecl);6484if (!Constructor)6485return QualType();6486// FIXME: Add support for Base class constructors as well.6487if (ValueDecl *MemberDecl = SemaRef.tryLookupCtorInitMemberDecl(6488Constructor->getParent(), SS, TemplateTypeTy, II))6489return ProduceConstructorSignatureHelp(MemberDecl->getType(),6490MemberDecl->getLocation(), ArgExprs,6491OpenParLoc, Braced);6492return QualType();6493}64946495static bool argMatchesTemplateParams(const ParsedTemplateArgument &Arg,6496unsigned Index,6497const TemplateParameterList &Params) {6498const NamedDecl *Param;6499if (Index < Params.size())6500Param = Params.getParam(Index);6501else if (Params.hasParameterPack())6502Param = Params.asArray().back();6503else6504return false; // too many args65056506switch (Arg.getKind()) {6507case ParsedTemplateArgument::Type:6508return llvm::isa<TemplateTypeParmDecl>(Param); // constraints not checked6509case ParsedTemplateArgument::NonType:6510return llvm::isa<NonTypeTemplateParmDecl>(Param); // type not checked6511case ParsedTemplateArgument::Template:6512return llvm::isa<TemplateTemplateParmDecl>(Param); // signature not checked6513}6514llvm_unreachable("Unhandled switch case");6515}65166517QualType SemaCodeCompletion::ProduceTemplateArgumentSignatureHelp(6518TemplateTy ParsedTemplate, ArrayRef<ParsedTemplateArgument> Args,6519SourceLocation LAngleLoc) {6520if (!CodeCompleter || !ParsedTemplate)6521return QualType();65226523SmallVector<ResultCandidate, 8> Results;6524auto Consider = [&](const TemplateDecl *TD) {6525// Only add if the existing args are compatible with the template.6526bool Matches = true;6527for (unsigned I = 0; I < Args.size(); ++I) {6528if (!argMatchesTemplateParams(Args[I], I, *TD->getTemplateParameters())) {6529Matches = false;6530break;6531}6532}6533if (Matches)6534Results.emplace_back(TD);6535};65366537TemplateName Template = ParsedTemplate.get();6538if (const auto *TD = Template.getAsTemplateDecl()) {6539Consider(TD);6540} else if (const auto *OTS = Template.getAsOverloadedTemplate()) {6541for (const NamedDecl *ND : *OTS)6542if (const auto *TD = llvm::dyn_cast<TemplateDecl>(ND))6543Consider(TD);6544}6545return ProduceSignatureHelp(SemaRef, Results, Args.size(), LAngleLoc,6546/*Braced=*/false);6547}65486549static QualType getDesignatedType(QualType BaseType, const Designation &Desig) {6550for (unsigned I = 0; I < Desig.getNumDesignators(); ++I) {6551if (BaseType.isNull())6552break;6553QualType NextType;6554const auto &D = Desig.getDesignator(I);6555if (D.isArrayDesignator() || D.isArrayRangeDesignator()) {6556if (BaseType->isArrayType())6557NextType = BaseType->getAsArrayTypeUnsafe()->getElementType();6558} else {6559assert(D.isFieldDesignator());6560auto *RD = getAsRecordDecl(BaseType);6561if (RD && RD->isCompleteDefinition()) {6562for (const auto *Member : RD->lookup(D.getFieldDecl()))6563if (const FieldDecl *FD = llvm::dyn_cast<FieldDecl>(Member)) {6564NextType = FD->getType();6565break;6566}6567}6568}6569BaseType = NextType;6570}6571return BaseType;6572}65736574void SemaCodeCompletion::CodeCompleteDesignator(6575QualType BaseType, llvm::ArrayRef<Expr *> InitExprs, const Designation &D) {6576BaseType = getDesignatedType(BaseType, D);6577if (BaseType.isNull())6578return;6579const auto *RD = getAsRecordDecl(BaseType);6580if (!RD || RD->fields().empty())6581return;65826583CodeCompletionContext CCC(CodeCompletionContext::CCC_DotMemberAccess,6584BaseType);6585ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6586CodeCompleter->getCodeCompletionTUInfo(), CCC);65876588Results.EnterNewScope();6589for (const Decl *D : RD->decls()) {6590const FieldDecl *FD;6591if (auto *IFD = dyn_cast<IndirectFieldDecl>(D))6592FD = IFD->getAnonField();6593else if (auto *DFD = dyn_cast<FieldDecl>(D))6594FD = DFD;6595else6596continue;65976598// FIXME: Make use of previous designators to mark any fields before those6599// inaccessible, and also compute the next initializer priority.6600ResultBuilder::Result Result(FD, Results.getBasePriority(FD));6601Results.AddResult(Result, SemaRef.CurContext, /*Hiding=*/nullptr);6602}6603Results.ExitScope();6604HandleCodeCompleteResults(&SemaRef, CodeCompleter,6605Results.getCompletionContext(), Results.data(),6606Results.size());6607}66086609void SemaCodeCompletion::CodeCompleteInitializer(Scope *S, Decl *D) {6610ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);6611if (!VD) {6612CodeCompleteOrdinaryName(S, PCC_Expression);6613return;6614}66156616CodeCompleteExpressionData Data;6617Data.PreferredType = VD->getType();6618// Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.6619Data.IgnoreDecls.push_back(VD);66206621CodeCompleteExpression(S, Data);6622}66236624void SemaCodeCompletion::CodeCompleteAfterIf(Scope *S, bool IsBracedThen) {6625ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6626CodeCompleter->getCodeCompletionTUInfo(),6627mapCodeCompletionContext(SemaRef, PCC_Statement));6628Results.setFilter(&ResultBuilder::IsOrdinaryName);6629Results.EnterNewScope();66306631CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);6632SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,6633CodeCompleter->includeGlobals(),6634CodeCompleter->loadExternal());66356636AddOrdinaryNameResults(PCC_Statement, S, SemaRef, Results);66376638// "else" block6639CodeCompletionBuilder Builder(Results.getAllocator(),6640Results.getCodeCompletionTUInfo());66416642auto AddElseBodyPattern = [&] {6643if (IsBracedThen) {6644Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);6645Builder.AddChunk(CodeCompletionString::CK_LeftBrace);6646Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);6647Builder.AddPlaceholderChunk("statements");6648Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);6649Builder.AddChunk(CodeCompletionString::CK_RightBrace);6650} else {6651Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);6652Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);6653Builder.AddPlaceholderChunk("statement");6654Builder.AddChunk(CodeCompletionString::CK_SemiColon);6655}6656};6657Builder.AddTypedTextChunk("else");6658if (Results.includeCodePatterns())6659AddElseBodyPattern();6660Results.AddResult(Builder.TakeString());66616662// "else if" block6663Builder.AddTypedTextChunk("else if");6664Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);6665Builder.AddChunk(CodeCompletionString::CK_LeftParen);6666if (getLangOpts().CPlusPlus)6667Builder.AddPlaceholderChunk("condition");6668else6669Builder.AddPlaceholderChunk("expression");6670Builder.AddChunk(CodeCompletionString::CK_RightParen);6671if (Results.includeCodePatterns()) {6672AddElseBodyPattern();6673}6674Results.AddResult(Builder.TakeString());66756676Results.ExitScope();66776678if (S->getFnParent())6679AddPrettyFunctionResults(getLangOpts(), Results);66806681if (CodeCompleter->includeMacros())6682AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false);66836684HandleCodeCompleteResults(&SemaRef, CodeCompleter,6685Results.getCompletionContext(), Results.data(),6686Results.size());6687}66886689void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,6690bool EnteringContext,6691bool IsUsingDeclaration,6692QualType BaseType,6693QualType PreferredType) {6694if (SS.isEmpty() || !CodeCompleter)6695return;66966697CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType);6698CC.setIsUsingDeclaration(IsUsingDeclaration);6699CC.setCXXScopeSpecifier(SS);67006701// We want to keep the scope specifier even if it's invalid (e.g. the scope6702// "a::b::" is not corresponding to any context/namespace in the AST), since6703// it can be useful for global code completion which have information about6704// contexts/symbols that are not in the AST.6705if (SS.isInvalid()) {6706// As SS is invalid, we try to collect accessible contexts from the current6707// scope with a dummy lookup so that the completion consumer can try to6708// guess what the specified scope is.6709ResultBuilder DummyResults(SemaRef, CodeCompleter->getAllocator(),6710CodeCompleter->getCodeCompletionTUInfo(), CC);6711if (!PreferredType.isNull())6712DummyResults.setPreferredType(PreferredType);6713if (S->getEntity()) {6714CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),6715BaseType);6716SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,6717/*IncludeGlobalScope=*/false,6718/*LoadExternal=*/false);6719}6720HandleCodeCompleteResults(&SemaRef, CodeCompleter,6721DummyResults.getCompletionContext(), nullptr, 0);6722return;6723}6724// Always pretend to enter a context to ensure that a dependent type6725// resolves to a dependent record.6726DeclContext *Ctx = SemaRef.computeDeclContext(SS, /*EnteringContext=*/true);67276728// Try to instantiate any non-dependent declaration contexts before6729// we look in them. Bail out if we fail.6730NestedNameSpecifier *NNS = SS.getScopeRep();6731if (NNS != nullptr && SS.isValid() && !NNS->isDependent()) {6732if (Ctx == nullptr || SemaRef.RequireCompleteDeclContext(SS, Ctx))6733return;6734}67356736ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6737CodeCompleter->getCodeCompletionTUInfo(), CC);6738if (!PreferredType.isNull())6739Results.setPreferredType(PreferredType);6740Results.EnterNewScope();67416742// The "template" keyword can follow "::" in the grammar, but only6743// put it into the grammar if the nested-name-specifier is dependent.6744// FIXME: results is always empty, this appears to be dead.6745if (!Results.empty() && NNS && NNS->isDependent())6746Results.AddResult("template");67476748// If the scope is a concept-constrained type parameter, infer nested6749// members based on the constraints.6750if (NNS) {6751if (const auto *TTPT =6752dyn_cast_or_null<TemplateTypeParmType>(NNS->getAsType())) {6753for (const auto &R : ConceptInfo(*TTPT, S).members()) {6754if (R.Operator != ConceptInfo::Member::Colons)6755continue;6756Results.AddResult(CodeCompletionResult(6757R.render(SemaRef, CodeCompleter->getAllocator(),6758CodeCompleter->getCodeCompletionTUInfo())));6759}6760}6761}67626763// Add calls to overridden virtual functions, if there are any.6764//6765// FIXME: This isn't wonderful, because we don't know whether we're actually6766// in a context that permits expressions. This is a general issue with6767// qualified-id completions.6768if (Ctx && !EnteringContext)6769MaybeAddOverrideCalls(SemaRef, Ctx, Results);6770Results.ExitScope();67716772if (Ctx &&6773(CodeCompleter->includeNamespaceLevelDecls() || !Ctx->isFileContext())) {6774CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);6775SemaRef.LookupVisibleDecls(Ctx, Sema::LookupOrdinaryName, Consumer,6776/*IncludeGlobalScope=*/true,6777/*IncludeDependentBases=*/true,6778CodeCompleter->loadExternal());6779}67806781HandleCodeCompleteResults(&SemaRef, CodeCompleter,6782Results.getCompletionContext(), Results.data(),6783Results.size());6784}67856786void SemaCodeCompletion::CodeCompleteUsing(Scope *S) {6787if (!CodeCompleter)6788return;67896790// This can be both a using alias or using declaration, in the former we6791// expect a new name and a symbol in the latter case.6792CodeCompletionContext Context(CodeCompletionContext::CCC_SymbolOrNewName);6793Context.setIsUsingDeclaration(true);67946795ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6796CodeCompleter->getCodeCompletionTUInfo(), Context,6797&ResultBuilder::IsNestedNameSpecifier);6798Results.EnterNewScope();67996800// If we aren't in class scope, we could see the "namespace" keyword.6801if (!S->isClassScope())6802Results.AddResult(CodeCompletionResult("namespace"));68036804// After "using", we can see anything that would start a6805// nested-name-specifier.6806CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);6807SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,6808CodeCompleter->includeGlobals(),6809CodeCompleter->loadExternal());6810Results.ExitScope();68116812HandleCodeCompleteResults(&SemaRef, CodeCompleter,6813Results.getCompletionContext(), Results.data(),6814Results.size());6815}68166817void SemaCodeCompletion::CodeCompleteUsingDirective(Scope *S) {6818if (!CodeCompleter)6819return;68206821// After "using namespace", we expect to see a namespace name or namespace6822// alias.6823ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6824CodeCompleter->getCodeCompletionTUInfo(),6825CodeCompletionContext::CCC_Namespace,6826&ResultBuilder::IsNamespaceOrAlias);6827Results.EnterNewScope();6828CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);6829SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,6830CodeCompleter->includeGlobals(),6831CodeCompleter->loadExternal());6832Results.ExitScope();6833HandleCodeCompleteResults(&SemaRef, CodeCompleter,6834Results.getCompletionContext(), Results.data(),6835Results.size());6836}68376838void SemaCodeCompletion::CodeCompleteNamespaceDecl(Scope *S) {6839if (!CodeCompleter)6840return;68416842DeclContext *Ctx = S->getEntity();6843if (!S->getParent())6844Ctx = getASTContext().getTranslationUnitDecl();68456846bool SuppressedGlobalResults =6847Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);68486849ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6850CodeCompleter->getCodeCompletionTUInfo(),6851SuppressedGlobalResults6852? CodeCompletionContext::CCC_Namespace6853: CodeCompletionContext::CCC_Other,6854&ResultBuilder::IsNamespace);68556856if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {6857// We only want to see those namespaces that have already been defined6858// within this scope, because its likely that the user is creating an6859// extended namespace declaration. Keep track of the most recent6860// definition of each namespace.6861std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;6862for (DeclContext::specific_decl_iterator<NamespaceDecl>6863NS(Ctx->decls_begin()),6864NSEnd(Ctx->decls_end());6865NS != NSEnd; ++NS)6866OrigToLatest[NS->getFirstDecl()] = *NS;68676868// Add the most recent definition (or extended definition) of each6869// namespace to the list of results.6870Results.EnterNewScope();6871for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator6872NS = OrigToLatest.begin(),6873NSEnd = OrigToLatest.end();6874NS != NSEnd; ++NS)6875Results.AddResult(6876CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),6877nullptr),6878SemaRef.CurContext, nullptr, false);6879Results.ExitScope();6880}68816882HandleCodeCompleteResults(&SemaRef, CodeCompleter,6883Results.getCompletionContext(), Results.data(),6884Results.size());6885}68866887void SemaCodeCompletion::CodeCompleteNamespaceAliasDecl(Scope *S) {6888if (!CodeCompleter)6889return;68906891// After "namespace", we expect to see a namespace or alias.6892ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6893CodeCompleter->getCodeCompletionTUInfo(),6894CodeCompletionContext::CCC_Namespace,6895&ResultBuilder::IsNamespaceOrAlias);6896CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);6897SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,6898CodeCompleter->includeGlobals(),6899CodeCompleter->loadExternal());6900HandleCodeCompleteResults(&SemaRef, CodeCompleter,6901Results.getCompletionContext(), Results.data(),6902Results.size());6903}69046905void SemaCodeCompletion::CodeCompleteOperatorName(Scope *S) {6906if (!CodeCompleter)6907return;69086909typedef CodeCompletionResult Result;6910ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6911CodeCompleter->getCodeCompletionTUInfo(),6912CodeCompletionContext::CCC_Type,6913&ResultBuilder::IsType);6914Results.EnterNewScope();69156916// Add the names of overloadable operators. Note that OO_Conditional is not6917// actually overloadable.6918#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \6919if (OO_##Name != OO_Conditional) \6920Results.AddResult(Result(Spelling));6921#include "clang/Basic/OperatorKinds.def"69226923// Add any type names visible from the current scope6924Results.allowNestedNameSpecifiers();6925CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);6926SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,6927CodeCompleter->includeGlobals(),6928CodeCompleter->loadExternal());69296930// Add any type specifiers6931AddTypeSpecifierResults(getLangOpts(), Results);6932Results.ExitScope();69336934HandleCodeCompleteResults(&SemaRef, CodeCompleter,6935Results.getCompletionContext(), Results.data(),6936Results.size());6937}69386939void SemaCodeCompletion::CodeCompleteConstructorInitializer(6940Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {6941if (!ConstructorD)6942return;69436944SemaRef.AdjustDeclIfTemplate(ConstructorD);69456946auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);6947if (!Constructor)6948return;69496950ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),6951CodeCompleter->getCodeCompletionTUInfo(),6952CodeCompletionContext::CCC_Symbol);6953Results.EnterNewScope();69546955// Fill in any already-initialized fields or base classes.6956llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;6957llvm::SmallPtrSet<CanQualType, 4> InitializedBases;6958for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {6959if (Initializers[I]->isBaseInitializer())6960InitializedBases.insert(getASTContext().getCanonicalType(6961QualType(Initializers[I]->getBaseClass(), 0)));6962else6963InitializedFields.insert(6964cast<FieldDecl>(Initializers[I]->getAnyMember()));6965}69666967// Add completions for base classes.6968PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);6969bool SawLastInitializer = Initializers.empty();6970CXXRecordDecl *ClassDecl = Constructor->getParent();69716972auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {6973CodeCompletionBuilder Builder(Results.getAllocator(),6974Results.getCodeCompletionTUInfo());6975Builder.AddTypedTextChunk(Name);6976Builder.AddChunk(CodeCompletionString::CK_LeftParen);6977if (const auto *Function = dyn_cast<FunctionDecl>(ND))6978AddFunctionParameterChunks(SemaRef.PP, Policy, Function, Builder);6979else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))6980AddFunctionParameterChunks(SemaRef.PP, Policy,6981FunTemplDecl->getTemplatedDecl(), Builder);6982Builder.AddChunk(CodeCompletionString::CK_RightParen);6983return Builder.TakeString();6984};6985auto AddDefaultCtorInit = [&](const char *Name, const char *Type,6986const NamedDecl *ND) {6987CodeCompletionBuilder Builder(Results.getAllocator(),6988Results.getCodeCompletionTUInfo());6989Builder.AddTypedTextChunk(Name);6990Builder.AddChunk(CodeCompletionString::CK_LeftParen);6991Builder.AddPlaceholderChunk(Type);6992Builder.AddChunk(CodeCompletionString::CK_RightParen);6993if (ND) {6994auto CCR = CodeCompletionResult(6995Builder.TakeString(), ND,6996SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);6997if (isa<FieldDecl>(ND))6998CCR.CursorKind = CXCursor_MemberRef;6999return Results.AddResult(CCR);7000}7001return Results.AddResult(CodeCompletionResult(7002Builder.TakeString(),7003SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));7004};7005auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,7006const char *Name, const FieldDecl *FD) {7007if (!RD)7008return AddDefaultCtorInit(Name,7009FD ? Results.getAllocator().CopyString(7010FD->getType().getAsString(Policy))7011: Name,7012FD);7013auto Ctors = getConstructors(getASTContext(), RD);7014if (Ctors.begin() == Ctors.end())7015return AddDefaultCtorInit(Name, Name, RD);7016for (const NamedDecl *Ctor : Ctors) {7017auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);7018CCR.CursorKind = getCursorKindForDecl(Ctor);7019Results.AddResult(CCR);7020}7021};7022auto AddBase = [&](const CXXBaseSpecifier &Base) {7023const char *BaseName =7024Results.getAllocator().CopyString(Base.getType().getAsString(Policy));7025const auto *RD = Base.getType()->getAsCXXRecordDecl();7026AddCtorsWithName(7027RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,7028BaseName, nullptr);7029};7030auto AddField = [&](const FieldDecl *FD) {7031const char *FieldName =7032Results.getAllocator().CopyString(FD->getIdentifier()->getName());7033const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();7034AddCtorsWithName(7035RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,7036FieldName, FD);7037};70387039for (const auto &Base : ClassDecl->bases()) {7040if (!InitializedBases7041.insert(getASTContext().getCanonicalType(Base.getType()))7042.second) {7043SawLastInitializer =7044!Initializers.empty() && Initializers.back()->isBaseInitializer() &&7045getASTContext().hasSameUnqualifiedType(7046Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));7047continue;7048}70497050AddBase(Base);7051SawLastInitializer = false;7052}70537054// Add completions for virtual base classes.7055for (const auto &Base : ClassDecl->vbases()) {7056if (!InitializedBases7057.insert(getASTContext().getCanonicalType(Base.getType()))7058.second) {7059SawLastInitializer =7060!Initializers.empty() && Initializers.back()->isBaseInitializer() &&7061getASTContext().hasSameUnqualifiedType(7062Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));7063continue;7064}70657066AddBase(Base);7067SawLastInitializer = false;7068}70697070// Add completions for members.7071for (auto *Field : ClassDecl->fields()) {7072if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))7073.second) {7074SawLastInitializer = !Initializers.empty() &&7075Initializers.back()->isAnyMemberInitializer() &&7076Initializers.back()->getAnyMember() == Field;7077continue;7078}70797080if (!Field->getDeclName())7081continue;70827083AddField(Field);7084SawLastInitializer = false;7085}7086Results.ExitScope();70877088HandleCodeCompleteResults(&SemaRef, CodeCompleter,7089Results.getCompletionContext(), Results.data(),7090Results.size());7091}70927093/// Determine whether this scope denotes a namespace.7094static bool isNamespaceScope(Scope *S) {7095DeclContext *DC = S->getEntity();7096if (!DC)7097return false;70987099return DC->isFileContext();7100}71017102void SemaCodeCompletion::CodeCompleteLambdaIntroducer(Scope *S,7103LambdaIntroducer &Intro,7104bool AfterAmpersand) {7105ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7106CodeCompleter->getCodeCompletionTUInfo(),7107CodeCompletionContext::CCC_Other);7108Results.EnterNewScope();71097110// Note what has already been captured.7111llvm::SmallPtrSet<IdentifierInfo *, 4> Known;7112bool IncludedThis = false;7113for (const auto &C : Intro.Captures) {7114if (C.Kind == LCK_This) {7115IncludedThis = true;7116continue;7117}71187119Known.insert(C.Id);7120}71217122// Look for other capturable variables.7123for (; S && !isNamespaceScope(S); S = S->getParent()) {7124for (const auto *D : S->decls()) {7125const auto *Var = dyn_cast<VarDecl>(D);7126if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())7127continue;71287129if (Known.insert(Var->getIdentifier()).second)7130Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),7131SemaRef.CurContext, nullptr, false);7132}7133}71347135// Add 'this', if it would be valid.7136if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)7137addThisCompletion(SemaRef, Results);71387139Results.ExitScope();71407141HandleCodeCompleteResults(&SemaRef, CodeCompleter,7142Results.getCompletionContext(), Results.data(),7143Results.size());7144}71457146void SemaCodeCompletion::CodeCompleteAfterFunctionEquals(Declarator &D) {7147if (!getLangOpts().CPlusPlus11)7148return;7149ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7150CodeCompleter->getCodeCompletionTUInfo(),7151CodeCompletionContext::CCC_Other);7152auto ShouldAddDefault = [&D, this]() {7153if (!D.isFunctionDeclarator())7154return false;7155auto &Id = D.getName();7156if (Id.getKind() == UnqualifiedIdKind::IK_DestructorName)7157return true;7158// FIXME(liuhui): Ideally, we should check the constructor parameter list to7159// verify that it is the default, copy or move constructor?7160if (Id.getKind() == UnqualifiedIdKind::IK_ConstructorName &&7161D.getFunctionTypeInfo().NumParams <= 1)7162return true;7163if (Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId) {7164auto Op = Id.OperatorFunctionId.Operator;7165// FIXME(liuhui): Ideally, we should check the function parameter list to7166// verify that it is the copy or move assignment?7167if (Op == OverloadedOperatorKind::OO_Equal)7168return true;7169if (getLangOpts().CPlusPlus20 &&7170(Op == OverloadedOperatorKind::OO_EqualEqual ||7171Op == OverloadedOperatorKind::OO_ExclaimEqual ||7172Op == OverloadedOperatorKind::OO_Less ||7173Op == OverloadedOperatorKind::OO_LessEqual ||7174Op == OverloadedOperatorKind::OO_Greater ||7175Op == OverloadedOperatorKind::OO_GreaterEqual ||7176Op == OverloadedOperatorKind::OO_Spaceship))7177return true;7178}7179return false;7180};71817182Results.EnterNewScope();7183if (ShouldAddDefault())7184Results.AddResult("default");7185// FIXME(liuhui): Ideally, we should only provide `delete` completion for the7186// first function declaration.7187Results.AddResult("delete");7188Results.ExitScope();7189HandleCodeCompleteResults(&SemaRef, CodeCompleter,7190Results.getCompletionContext(), Results.data(),7191Results.size());7192}71937194/// Macro that optionally prepends an "@" to the string literal passed in via7195/// Keyword, depending on whether NeedAt is true or false.7196#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)71977198static void AddObjCImplementationResults(const LangOptions &LangOpts,7199ResultBuilder &Results, bool NeedAt) {7200typedef CodeCompletionResult Result;7201// Since we have an implementation, we can end it.7202Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));72037204CodeCompletionBuilder Builder(Results.getAllocator(),7205Results.getCodeCompletionTUInfo());7206if (LangOpts.ObjC) {7207// @dynamic7208Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));7209Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7210Builder.AddPlaceholderChunk("property");7211Results.AddResult(Result(Builder.TakeString()));72127213// @synthesize7214Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));7215Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7216Builder.AddPlaceholderChunk("property");7217Results.AddResult(Result(Builder.TakeString()));7218}7219}72207221static void AddObjCInterfaceResults(const LangOptions &LangOpts,7222ResultBuilder &Results, bool NeedAt) {7223typedef CodeCompletionResult Result;72247225// Since we have an interface or protocol, we can end it.7226Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));72277228if (LangOpts.ObjC) {7229// @property7230Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));72317232// @required7233Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));72347235// @optional7236Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));7237}7238}72397240static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {7241typedef CodeCompletionResult Result;7242CodeCompletionBuilder Builder(Results.getAllocator(),7243Results.getCodeCompletionTUInfo());72447245// @class name ;7246Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));7247Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7248Builder.AddPlaceholderChunk("name");7249Results.AddResult(Result(Builder.TakeString()));72507251if (Results.includeCodePatterns()) {7252// @interface name7253// FIXME: Could introduce the whole pattern, including superclasses and7254// such.7255Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));7256Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7257Builder.AddPlaceholderChunk("class");7258Results.AddResult(Result(Builder.TakeString()));72597260// @protocol name7261Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));7262Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7263Builder.AddPlaceholderChunk("protocol");7264Results.AddResult(Result(Builder.TakeString()));72657266// @implementation name7267Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));7268Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7269Builder.AddPlaceholderChunk("class");7270Results.AddResult(Result(Builder.TakeString()));7271}72727273// @compatibility_alias name7274Builder.AddTypedTextChunk(7275OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));7276Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7277Builder.AddPlaceholderChunk("alias");7278Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7279Builder.AddPlaceholderChunk("class");7280Results.AddResult(Result(Builder.TakeString()));72817282if (Results.getSema().getLangOpts().Modules) {7283// @import name7284Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));7285Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7286Builder.AddPlaceholderChunk("module");7287Results.AddResult(Result(Builder.TakeString()));7288}7289}72907291void SemaCodeCompletion::CodeCompleteObjCAtDirective(Scope *S) {7292ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7293CodeCompleter->getCodeCompletionTUInfo(),7294CodeCompletionContext::CCC_Other);7295Results.EnterNewScope();7296if (isa<ObjCImplDecl>(SemaRef.CurContext))7297AddObjCImplementationResults(getLangOpts(), Results, false);7298else if (SemaRef.CurContext->isObjCContainer())7299AddObjCInterfaceResults(getLangOpts(), Results, false);7300else7301AddObjCTopLevelResults(Results, false);7302Results.ExitScope();7303HandleCodeCompleteResults(&SemaRef, CodeCompleter,7304Results.getCompletionContext(), Results.data(),7305Results.size());7306}73077308static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {7309typedef CodeCompletionResult Result;7310CodeCompletionBuilder Builder(Results.getAllocator(),7311Results.getCodeCompletionTUInfo());73127313// @encode ( type-name )7314const char *EncodeType = "char[]";7315if (Results.getSema().getLangOpts().CPlusPlus ||7316Results.getSema().getLangOpts().ConstStrings)7317EncodeType = "const char[]";7318Builder.AddResultTypeChunk(EncodeType);7319Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));7320Builder.AddChunk(CodeCompletionString::CK_LeftParen);7321Builder.AddPlaceholderChunk("type-name");7322Builder.AddChunk(CodeCompletionString::CK_RightParen);7323Results.AddResult(Result(Builder.TakeString()));73247325// @protocol ( protocol-name )7326Builder.AddResultTypeChunk("Protocol *");7327Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));7328Builder.AddChunk(CodeCompletionString::CK_LeftParen);7329Builder.AddPlaceholderChunk("protocol-name");7330Builder.AddChunk(CodeCompletionString::CK_RightParen);7331Results.AddResult(Result(Builder.TakeString()));73327333// @selector ( selector )7334Builder.AddResultTypeChunk("SEL");7335Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));7336Builder.AddChunk(CodeCompletionString::CK_LeftParen);7337Builder.AddPlaceholderChunk("selector");7338Builder.AddChunk(CodeCompletionString::CK_RightParen);7339Results.AddResult(Result(Builder.TakeString()));73407341// @"string"7342Builder.AddResultTypeChunk("NSString *");7343Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));7344Builder.AddPlaceholderChunk("string");7345Builder.AddTextChunk("\"");7346Results.AddResult(Result(Builder.TakeString()));73477348// @[objects, ...]7349Builder.AddResultTypeChunk("NSArray *");7350Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));7351Builder.AddPlaceholderChunk("objects, ...");7352Builder.AddChunk(CodeCompletionString::CK_RightBracket);7353Results.AddResult(Result(Builder.TakeString()));73547355// @{key : object, ...}7356Builder.AddResultTypeChunk("NSDictionary *");7357Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));7358Builder.AddPlaceholderChunk("key");7359Builder.AddChunk(CodeCompletionString::CK_Colon);7360Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7361Builder.AddPlaceholderChunk("object, ...");7362Builder.AddChunk(CodeCompletionString::CK_RightBrace);7363Results.AddResult(Result(Builder.TakeString()));73647365// @(expression)7366Builder.AddResultTypeChunk("id");7367Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));7368Builder.AddPlaceholderChunk("expression");7369Builder.AddChunk(CodeCompletionString::CK_RightParen);7370Results.AddResult(Result(Builder.TakeString()));7371}73727373static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {7374typedef CodeCompletionResult Result;7375CodeCompletionBuilder Builder(Results.getAllocator(),7376Results.getCodeCompletionTUInfo());73777378if (Results.includeCodePatterns()) {7379// @try { statements } @catch ( declaration ) { statements } @finally7380// { statements }7381Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));7382Builder.AddChunk(CodeCompletionString::CK_LeftBrace);7383Builder.AddPlaceholderChunk("statements");7384Builder.AddChunk(CodeCompletionString::CK_RightBrace);7385Builder.AddTextChunk("@catch");7386Builder.AddChunk(CodeCompletionString::CK_LeftParen);7387Builder.AddPlaceholderChunk("parameter");7388Builder.AddChunk(CodeCompletionString::CK_RightParen);7389Builder.AddChunk(CodeCompletionString::CK_LeftBrace);7390Builder.AddPlaceholderChunk("statements");7391Builder.AddChunk(CodeCompletionString::CK_RightBrace);7392Builder.AddTextChunk("@finally");7393Builder.AddChunk(CodeCompletionString::CK_LeftBrace);7394Builder.AddPlaceholderChunk("statements");7395Builder.AddChunk(CodeCompletionString::CK_RightBrace);7396Results.AddResult(Result(Builder.TakeString()));7397}73987399// @throw7400Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));7401Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7402Builder.AddPlaceholderChunk("expression");7403Results.AddResult(Result(Builder.TakeString()));74047405if (Results.includeCodePatterns()) {7406// @synchronized ( expression ) { statements }7407Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));7408Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);7409Builder.AddChunk(CodeCompletionString::CK_LeftParen);7410Builder.AddPlaceholderChunk("expression");7411Builder.AddChunk(CodeCompletionString::CK_RightParen);7412Builder.AddChunk(CodeCompletionString::CK_LeftBrace);7413Builder.AddPlaceholderChunk("statements");7414Builder.AddChunk(CodeCompletionString::CK_RightBrace);7415Results.AddResult(Result(Builder.TakeString()));7416}7417}74187419static void AddObjCVisibilityResults(const LangOptions &LangOpts,7420ResultBuilder &Results, bool NeedAt) {7421typedef CodeCompletionResult Result;7422Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));7423Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));7424Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));7425if (LangOpts.ObjC)7426Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));7427}74287429void SemaCodeCompletion::CodeCompleteObjCAtVisibility(Scope *S) {7430ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7431CodeCompleter->getCodeCompletionTUInfo(),7432CodeCompletionContext::CCC_Other);7433Results.EnterNewScope();7434AddObjCVisibilityResults(getLangOpts(), Results, false);7435Results.ExitScope();7436HandleCodeCompleteResults(&SemaRef, CodeCompleter,7437Results.getCompletionContext(), Results.data(),7438Results.size());7439}74407441void SemaCodeCompletion::CodeCompleteObjCAtStatement(Scope *S) {7442ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7443CodeCompleter->getCodeCompletionTUInfo(),7444CodeCompletionContext::CCC_Other);7445Results.EnterNewScope();7446AddObjCStatementResults(Results, false);7447AddObjCExpressionResults(Results, false);7448Results.ExitScope();7449HandleCodeCompleteResults(&SemaRef, CodeCompleter,7450Results.getCompletionContext(), Results.data(),7451Results.size());7452}74537454void SemaCodeCompletion::CodeCompleteObjCAtExpression(Scope *S) {7455ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7456CodeCompleter->getCodeCompletionTUInfo(),7457CodeCompletionContext::CCC_Other);7458Results.EnterNewScope();7459AddObjCExpressionResults(Results, false);7460Results.ExitScope();7461HandleCodeCompleteResults(&SemaRef, CodeCompleter,7462Results.getCompletionContext(), Results.data(),7463Results.size());7464}74657466/// Determine whether the addition of the given flag to an Objective-C7467/// property's attributes will cause a conflict.7468static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {7469// Check if we've already added this flag.7470if (Attributes & NewFlag)7471return true;74727473Attributes |= NewFlag;74747475// Check for collisions with "readonly".7476if ((Attributes & ObjCPropertyAttribute::kind_readonly) &&7477(Attributes & ObjCPropertyAttribute::kind_readwrite))7478return true;74797480// Check for more than one of { assign, copy, retain, strong, weak }.7481unsigned AssignCopyRetMask =7482Attributes &7483(ObjCPropertyAttribute::kind_assign |7484ObjCPropertyAttribute::kind_unsafe_unretained |7485ObjCPropertyAttribute::kind_copy | ObjCPropertyAttribute::kind_retain |7486ObjCPropertyAttribute::kind_strong | ObjCPropertyAttribute::kind_weak);7487if (AssignCopyRetMask &&7488AssignCopyRetMask != ObjCPropertyAttribute::kind_assign &&7489AssignCopyRetMask != ObjCPropertyAttribute::kind_unsafe_unretained &&7490AssignCopyRetMask != ObjCPropertyAttribute::kind_copy &&7491AssignCopyRetMask != ObjCPropertyAttribute::kind_retain &&7492AssignCopyRetMask != ObjCPropertyAttribute::kind_strong &&7493AssignCopyRetMask != ObjCPropertyAttribute::kind_weak)7494return true;74957496return false;7497}74987499void SemaCodeCompletion::CodeCompleteObjCPropertyFlags(Scope *S,7500ObjCDeclSpec &ODS) {7501if (!CodeCompleter)7502return;75037504unsigned Attributes = ODS.getPropertyAttributes();75057506ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7507CodeCompleter->getCodeCompletionTUInfo(),7508CodeCompletionContext::CCC_Other);7509Results.EnterNewScope();7510if (!ObjCPropertyFlagConflicts(Attributes,7511ObjCPropertyAttribute::kind_readonly))7512Results.AddResult(CodeCompletionResult("readonly"));7513if (!ObjCPropertyFlagConflicts(Attributes,7514ObjCPropertyAttribute::kind_assign))7515Results.AddResult(CodeCompletionResult("assign"));7516if (!ObjCPropertyFlagConflicts(Attributes,7517ObjCPropertyAttribute::kind_unsafe_unretained))7518Results.AddResult(CodeCompletionResult("unsafe_unretained"));7519if (!ObjCPropertyFlagConflicts(Attributes,7520ObjCPropertyAttribute::kind_readwrite))7521Results.AddResult(CodeCompletionResult("readwrite"));7522if (!ObjCPropertyFlagConflicts(Attributes,7523ObjCPropertyAttribute::kind_retain))7524Results.AddResult(CodeCompletionResult("retain"));7525if (!ObjCPropertyFlagConflicts(Attributes,7526ObjCPropertyAttribute::kind_strong))7527Results.AddResult(CodeCompletionResult("strong"));7528if (!ObjCPropertyFlagConflicts(Attributes, ObjCPropertyAttribute::kind_copy))7529Results.AddResult(CodeCompletionResult("copy"));7530if (!ObjCPropertyFlagConflicts(Attributes,7531ObjCPropertyAttribute::kind_nonatomic))7532Results.AddResult(CodeCompletionResult("nonatomic"));7533if (!ObjCPropertyFlagConflicts(Attributes,7534ObjCPropertyAttribute::kind_atomic))7535Results.AddResult(CodeCompletionResult("atomic"));75367537// Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.7538if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)7539if (!ObjCPropertyFlagConflicts(Attributes,7540ObjCPropertyAttribute::kind_weak))7541Results.AddResult(CodeCompletionResult("weak"));75427543if (!ObjCPropertyFlagConflicts(Attributes,7544ObjCPropertyAttribute::kind_setter)) {7545CodeCompletionBuilder Setter(Results.getAllocator(),7546Results.getCodeCompletionTUInfo());7547Setter.AddTypedTextChunk("setter");7548Setter.AddTextChunk("=");7549Setter.AddPlaceholderChunk("method");7550Results.AddResult(CodeCompletionResult(Setter.TakeString()));7551}7552if (!ObjCPropertyFlagConflicts(Attributes,7553ObjCPropertyAttribute::kind_getter)) {7554CodeCompletionBuilder Getter(Results.getAllocator(),7555Results.getCodeCompletionTUInfo());7556Getter.AddTypedTextChunk("getter");7557Getter.AddTextChunk("=");7558Getter.AddPlaceholderChunk("method");7559Results.AddResult(CodeCompletionResult(Getter.TakeString()));7560}7561if (!ObjCPropertyFlagConflicts(Attributes,7562ObjCPropertyAttribute::kind_nullability)) {7563Results.AddResult(CodeCompletionResult("nonnull"));7564Results.AddResult(CodeCompletionResult("nullable"));7565Results.AddResult(CodeCompletionResult("null_unspecified"));7566Results.AddResult(CodeCompletionResult("null_resettable"));7567}7568Results.ExitScope();7569HandleCodeCompleteResults(&SemaRef, CodeCompleter,7570Results.getCompletionContext(), Results.data(),7571Results.size());7572}75737574/// Describes the kind of Objective-C method that we want to find7575/// via code completion.7576enum ObjCMethodKind {7577MK_Any, ///< Any kind of method, provided it means other specified criteria.7578MK_ZeroArgSelector, ///< Zero-argument (unary) selector.7579MK_OneArgSelector ///< One-argument selector.7580};75817582static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,7583ArrayRef<const IdentifierInfo *> SelIdents,7584bool AllowSameLength = true) {7585unsigned NumSelIdents = SelIdents.size();7586if (NumSelIdents > Sel.getNumArgs())7587return false;75887589switch (WantKind) {7590case MK_Any:7591break;7592case MK_ZeroArgSelector:7593return Sel.isUnarySelector();7594case MK_OneArgSelector:7595return Sel.getNumArgs() == 1;7596}75977598if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())7599return false;76007601for (unsigned I = 0; I != NumSelIdents; ++I)7602if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))7603return false;76047605return true;7606}76077608static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,7609ObjCMethodKind WantKind,7610ArrayRef<const IdentifierInfo *> SelIdents,7611bool AllowSameLength = true) {7612return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,7613AllowSameLength);7614}76157616/// A set of selectors, which is used to avoid introducing multiple7617/// completions with the same selector into the result set.7618typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;76197620/// Add all of the Objective-C methods in the given Objective-C7621/// container to the set of results.7622///7623/// The container will be a class, protocol, category, or implementation of7624/// any of the above. This mether will recurse to include methods from7625/// the superclasses of classes along with their categories, protocols, and7626/// implementations.7627///7628/// \param Container the container in which we'll look to find methods.7629///7630/// \param WantInstanceMethods Whether to add instance methods (only); if7631/// false, this routine will add factory methods (only).7632///7633/// \param CurContext the context in which we're performing the lookup that7634/// finds methods.7635///7636/// \param AllowSameLength Whether we allow a method to be added to the list7637/// when it has the same number of parameters as we have selector identifiers.7638///7639/// \param Results the structure into which we'll add results.7640static void AddObjCMethods(ObjCContainerDecl *Container,7641bool WantInstanceMethods, ObjCMethodKind WantKind,7642ArrayRef<const IdentifierInfo *> SelIdents,7643DeclContext *CurContext,7644VisitedSelectorSet &Selectors, bool AllowSameLength,7645ResultBuilder &Results, bool InOriginalClass = true,7646bool IsRootClass = false) {7647typedef CodeCompletionResult Result;7648Container = getContainerDef(Container);7649ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);7650IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());7651for (ObjCMethodDecl *M : Container->methods()) {7652// The instance methods on the root class can be messaged via the7653// metaclass.7654if (M->isInstanceMethod() == WantInstanceMethods ||7655(IsRootClass && !WantInstanceMethods)) {7656// Check whether the selector identifiers we've been given are a7657// subset of the identifiers for this particular method.7658if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))7659continue;76607661if (!Selectors.insert(M->getSelector()).second)7662continue;76637664Result R = Result(M, Results.getBasePriority(M), nullptr);7665R.StartParameter = SelIdents.size();7666R.AllParametersAreInformative = (WantKind != MK_Any);7667if (!InOriginalClass)7668setInBaseClass(R);7669Results.MaybeAddResult(R, CurContext);7670}7671}76727673// Visit the protocols of protocols.7674if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {7675if (Protocol->hasDefinition()) {7676const ObjCList<ObjCProtocolDecl> &Protocols =7677Protocol->getReferencedProtocols();7678for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),7679E = Protocols.end();7680I != E; ++I)7681AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,7682Selectors, AllowSameLength, Results, false, IsRootClass);7683}7684}76857686if (!IFace || !IFace->hasDefinition())7687return;76887689// Add methods in protocols.7690for (ObjCProtocolDecl *I : IFace->protocols())7691AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,7692Selectors, AllowSameLength, Results, false, IsRootClass);76937694// Add methods in categories.7695for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {7696AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,7697CurContext, Selectors, AllowSameLength, Results,7698InOriginalClass, IsRootClass);76997700// Add a categories protocol methods.7701const ObjCList<ObjCProtocolDecl> &Protocols =7702CatDecl->getReferencedProtocols();7703for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),7704E = Protocols.end();7705I != E; ++I)7706AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,7707Selectors, AllowSameLength, Results, false, IsRootClass);77087709// Add methods in category implementations.7710if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())7711AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,7712Selectors, AllowSameLength, Results, InOriginalClass,7713IsRootClass);7714}77157716// Add methods in superclass.7717// Avoid passing in IsRootClass since root classes won't have super classes.7718if (IFace->getSuperClass())7719AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,7720SelIdents, CurContext, Selectors, AllowSameLength, Results,7721/*IsRootClass=*/false);77227723// Add methods in our implementation, if any.7724if (ObjCImplementationDecl *Impl = IFace->getImplementation())7725AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,7726Selectors, AllowSameLength, Results, InOriginalClass,7727IsRootClass);7728}77297730void SemaCodeCompletion::CodeCompleteObjCPropertyGetter(Scope *S) {7731// Try to find the interface where getters might live.7732ObjCInterfaceDecl *Class =7733dyn_cast_or_null<ObjCInterfaceDecl>(SemaRef.CurContext);7734if (!Class) {7735if (ObjCCategoryDecl *Category =7736dyn_cast_or_null<ObjCCategoryDecl>(SemaRef.CurContext))7737Class = Category->getClassInterface();77387739if (!Class)7740return;7741}77427743// Find all of the potential getters.7744ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7745CodeCompleter->getCodeCompletionTUInfo(),7746CodeCompletionContext::CCC_Other);7747Results.EnterNewScope();77487749VisitedSelectorSet Selectors;7750AddObjCMethods(Class, true, MK_ZeroArgSelector, std::nullopt,7751SemaRef.CurContext, Selectors,7752/*AllowSameLength=*/true, Results);7753Results.ExitScope();7754HandleCodeCompleteResults(&SemaRef, CodeCompleter,7755Results.getCompletionContext(), Results.data(),7756Results.size());7757}77587759void SemaCodeCompletion::CodeCompleteObjCPropertySetter(Scope *S) {7760// Try to find the interface where setters might live.7761ObjCInterfaceDecl *Class =7762dyn_cast_or_null<ObjCInterfaceDecl>(SemaRef.CurContext);7763if (!Class) {7764if (ObjCCategoryDecl *Category =7765dyn_cast_or_null<ObjCCategoryDecl>(SemaRef.CurContext))7766Class = Category->getClassInterface();77677768if (!Class)7769return;7770}77717772// Find all of the potential getters.7773ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7774CodeCompleter->getCodeCompletionTUInfo(),7775CodeCompletionContext::CCC_Other);7776Results.EnterNewScope();77777778VisitedSelectorSet Selectors;7779AddObjCMethods(Class, true, MK_OneArgSelector, std::nullopt,7780SemaRef.CurContext, Selectors,7781/*AllowSameLength=*/true, Results);77827783Results.ExitScope();7784HandleCodeCompleteResults(&SemaRef, CodeCompleter,7785Results.getCompletionContext(), Results.data(),7786Results.size());7787}77887789void SemaCodeCompletion::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,7790bool IsParameter) {7791ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),7792CodeCompleter->getCodeCompletionTUInfo(),7793CodeCompletionContext::CCC_Type);7794Results.EnterNewScope();77957796// Add context-sensitive, Objective-C parameter-passing keywords.7797bool AddedInOut = false;7798if ((DS.getObjCDeclQualifier() &7799(ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {7800Results.AddResult("in");7801Results.AddResult("inout");7802AddedInOut = true;7803}7804if ((DS.getObjCDeclQualifier() &7805(ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {7806Results.AddResult("out");7807if (!AddedInOut)7808Results.AddResult("inout");7809}7810if ((DS.getObjCDeclQualifier() &7811(ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |7812ObjCDeclSpec::DQ_Oneway)) == 0) {7813Results.AddResult("bycopy");7814Results.AddResult("byref");7815Results.AddResult("oneway");7816}7817if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {7818Results.AddResult("nonnull");7819Results.AddResult("nullable");7820Results.AddResult("null_unspecified");7821}78227823// If we're completing the return type of an Objective-C method and the7824// identifier IBAction refers to a macro, provide a completion item for7825// an action, e.g.,7826// IBAction)<#selector#>:(id)sender7827if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&7828SemaRef.PP.isMacroDefined("IBAction")) {7829CodeCompletionBuilder Builder(Results.getAllocator(),7830Results.getCodeCompletionTUInfo(),7831CCP_CodePattern, CXAvailability_Available);7832Builder.AddTypedTextChunk("IBAction");7833Builder.AddChunk(CodeCompletionString::CK_RightParen);7834Builder.AddPlaceholderChunk("selector");7835Builder.AddChunk(CodeCompletionString::CK_Colon);7836Builder.AddChunk(CodeCompletionString::CK_LeftParen);7837Builder.AddTextChunk("id");7838Builder.AddChunk(CodeCompletionString::CK_RightParen);7839Builder.AddTextChunk("sender");7840Results.AddResult(CodeCompletionResult(Builder.TakeString()));7841}78427843// If we're completing the return type, provide 'instancetype'.7844if (!IsParameter) {7845Results.AddResult(CodeCompletionResult("instancetype"));7846}78477848// Add various builtin type names and specifiers.7849AddOrdinaryNameResults(PCC_Type, S, SemaRef, Results);7850Results.ExitScope();78517852// Add the various type names7853Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);7854CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);7855SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,7856CodeCompleter->includeGlobals(),7857CodeCompleter->loadExternal());78587859if (CodeCompleter->includeMacros())7860AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false);78617862HandleCodeCompleteResults(&SemaRef, CodeCompleter,7863Results.getCompletionContext(), Results.data(),7864Results.size());7865}78667867/// When we have an expression with type "id", we may assume7868/// that it has some more-specific class type based on knowledge of7869/// common uses of Objective-C. This routine returns that class type,7870/// or NULL if no better result could be determined.7871static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {7872auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);7873if (!Msg)7874return nullptr;78757876Selector Sel = Msg->getSelector();7877if (Sel.isNull())7878return nullptr;78797880const IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);7881if (!Id)7882return nullptr;78837884ObjCMethodDecl *Method = Msg->getMethodDecl();7885if (!Method)7886return nullptr;78877888// Determine the class that we're sending the message to.7889ObjCInterfaceDecl *IFace = nullptr;7890switch (Msg->getReceiverKind()) {7891case ObjCMessageExpr::Class:7892if (const ObjCObjectType *ObjType =7893Msg->getClassReceiver()->getAs<ObjCObjectType>())7894IFace = ObjType->getInterface();7895break;78967897case ObjCMessageExpr::Instance: {7898QualType T = Msg->getInstanceReceiver()->getType();7899if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())7900IFace = Ptr->getInterfaceDecl();7901break;7902}79037904case ObjCMessageExpr::SuperInstance:7905case ObjCMessageExpr::SuperClass:7906break;7907}79087909if (!IFace)7910return nullptr;79117912ObjCInterfaceDecl *Super = IFace->getSuperClass();7913if (Method->isInstanceMethod())7914return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())7915.Case("retain", IFace)7916.Case("strong", IFace)7917.Case("autorelease", IFace)7918.Case("copy", IFace)7919.Case("copyWithZone", IFace)7920.Case("mutableCopy", IFace)7921.Case("mutableCopyWithZone", IFace)7922.Case("awakeFromCoder", IFace)7923.Case("replacementObjectFromCoder", IFace)7924.Case("class", IFace)7925.Case("classForCoder", IFace)7926.Case("superclass", Super)7927.Default(nullptr);79287929return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())7930.Case("new", IFace)7931.Case("alloc", IFace)7932.Case("allocWithZone", IFace)7933.Case("class", IFace)7934.Case("superclass", Super)7935.Default(nullptr);7936}79377938// Add a special completion for a message send to "super", which fills in the7939// most likely case of forwarding all of our arguments to the superclass7940// function.7941///7942/// \param S The semantic analysis object.7943///7944/// \param NeedSuperKeyword Whether we need to prefix this completion with7945/// the "super" keyword. Otherwise, we just need to provide the arguments.7946///7947/// \param SelIdents The identifiers in the selector that have already been7948/// provided as arguments for a send to "super".7949///7950/// \param Results The set of results to augment.7951///7952/// \returns the Objective-C method declaration that would be invoked by7953/// this "super" completion. If NULL, no completion was added.7954static ObjCMethodDecl *7955AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,7956ArrayRef<const IdentifierInfo *> SelIdents,7957ResultBuilder &Results) {7958ObjCMethodDecl *CurMethod = S.getCurMethodDecl();7959if (!CurMethod)7960return nullptr;79617962ObjCInterfaceDecl *Class = CurMethod->getClassInterface();7963if (!Class)7964return nullptr;79657966// Try to find a superclass method with the same selector.7967ObjCMethodDecl *SuperMethod = nullptr;7968while ((Class = Class->getSuperClass()) && !SuperMethod) {7969// Check in the class7970SuperMethod = Class->getMethod(CurMethod->getSelector(),7971CurMethod->isInstanceMethod());79727973// Check in categories or class extensions.7974if (!SuperMethod) {7975for (const auto *Cat : Class->known_categories()) {7976if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),7977CurMethod->isInstanceMethod())))7978break;7979}7980}7981}79827983if (!SuperMethod)7984return nullptr;79857986// Check whether the superclass method has the same signature.7987if (CurMethod->param_size() != SuperMethod->param_size() ||7988CurMethod->isVariadic() != SuperMethod->isVariadic())7989return nullptr;79907991for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),7992CurPEnd = CurMethod->param_end(),7993SuperP = SuperMethod->param_begin();7994CurP != CurPEnd; ++CurP, ++SuperP) {7995// Make sure the parameter types are compatible.7996if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),7997(*SuperP)->getType()))7998return nullptr;79998000// Make sure we have a parameter name to forward!8001if (!(*CurP)->getIdentifier())8002return nullptr;8003}80048005// We have a superclass method. Now, form the send-to-super completion.8006CodeCompletionBuilder Builder(Results.getAllocator(),8007Results.getCodeCompletionTUInfo());80088009// Give this completion a return type.8010AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,8011Results.getCompletionContext().getBaseType(), Builder);80128013// If we need the "super" keyword, add it (plus some spacing).8014if (NeedSuperKeyword) {8015Builder.AddTypedTextChunk("super");8016Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);8017}80188019Selector Sel = CurMethod->getSelector();8020if (Sel.isUnarySelector()) {8021if (NeedSuperKeyword)8022Builder.AddTextChunk(8023Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));8024else8025Builder.AddTypedTextChunk(8026Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));8027} else {8028ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();8029for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {8030if (I > SelIdents.size())8031Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);80328033if (I < SelIdents.size())8034Builder.AddInformativeChunk(8035Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));8036else if (NeedSuperKeyword || I > SelIdents.size()) {8037Builder.AddTextChunk(8038Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));8039Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(8040(*CurP)->getIdentifier()->getName()));8041} else {8042Builder.AddTypedTextChunk(8043Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));8044Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(8045(*CurP)->getIdentifier()->getName()));8046}8047}8048}80498050Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,8051CCP_SuperCompletion));8052return SuperMethod;8053}80548055void SemaCodeCompletion::CodeCompleteObjCMessageReceiver(Scope *S) {8056typedef CodeCompletionResult Result;8057ResultBuilder Results(8058SemaRef, CodeCompleter->getAllocator(),8059CodeCompleter->getCodeCompletionTUInfo(),8060CodeCompletionContext::CCC_ObjCMessageReceiver,8061getLangOpts().CPlusPlus118062? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture8063: &ResultBuilder::IsObjCMessageReceiver);80648065CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);8066Results.EnterNewScope();8067SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,8068CodeCompleter->includeGlobals(),8069CodeCompleter->loadExternal());80708071// If we are in an Objective-C method inside a class that has a superclass,8072// add "super" as an option.8073if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())8074if (ObjCInterfaceDecl *Iface = Method->getClassInterface())8075if (Iface->getSuperClass()) {8076Results.AddResult(Result("super"));80778078AddSuperSendCompletion(SemaRef, /*NeedSuperKeyword=*/true, std::nullopt,8079Results);8080}80818082if (getLangOpts().CPlusPlus11)8083addThisCompletion(SemaRef, Results);80848085Results.ExitScope();80868087if (CodeCompleter->includeMacros())8088AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), false);8089HandleCodeCompleteResults(&SemaRef, CodeCompleter,8090Results.getCompletionContext(), Results.data(),8091Results.size());8092}80938094void SemaCodeCompletion::CodeCompleteObjCSuperMessage(8095Scope *S, SourceLocation SuperLoc,8096ArrayRef<const IdentifierInfo *> SelIdents, bool AtArgumentExpression) {8097ObjCInterfaceDecl *CDecl = nullptr;8098if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) {8099// Figure out which interface we're in.8100CDecl = CurMethod->getClassInterface();8101if (!CDecl)8102return;81038104// Find the superclass of this class.8105CDecl = CDecl->getSuperClass();8106if (!CDecl)8107return;81088109if (CurMethod->isInstanceMethod()) {8110// We are inside an instance method, which means that the message8111// send [super ...] is actually calling an instance method on the8112// current object.8113return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,8114AtArgumentExpression, CDecl);8115}81168117// Fall through to send to the superclass in CDecl.8118} else {8119// "super" may be the name of a type or variable. Figure out which8120// it is.8121const IdentifierInfo *Super = SemaRef.getSuperIdentifier();8122NamedDecl *ND =8123SemaRef.LookupSingleName(S, Super, SuperLoc, Sema::LookupOrdinaryName);8124if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {8125// "super" names an interface. Use it.8126} else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {8127if (const ObjCObjectType *Iface =8128getASTContext().getTypeDeclType(TD)->getAs<ObjCObjectType>())8129CDecl = Iface->getInterface();8130} else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {8131// "super" names an unresolved type; we can't be more specific.8132} else {8133// Assume that "super" names some kind of value and parse that way.8134CXXScopeSpec SS;8135SourceLocation TemplateKWLoc;8136UnqualifiedId id;8137id.setIdentifier(Super, SuperLoc);8138ExprResult SuperExpr =8139SemaRef.ActOnIdExpression(S, SS, TemplateKWLoc, id,8140/*HasTrailingLParen=*/false,8141/*IsAddressOfOperand=*/false);8142return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),8143SelIdents, AtArgumentExpression);8144}81458146// Fall through8147}81488149ParsedType Receiver;8150if (CDecl)8151Receiver = ParsedType::make(getASTContext().getObjCInterfaceType(CDecl));8152return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,8153AtArgumentExpression,8154/*IsSuper=*/true);8155}81568157/// Given a set of code-completion results for the argument of a message8158/// send, determine the preferred type (if any) for that argument expression.8159static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,8160unsigned NumSelIdents) {8161typedef CodeCompletionResult Result;8162ASTContext &Context = Results.getSema().Context;81638164QualType PreferredType;8165unsigned BestPriority = CCP_Unlikely * 2;8166Result *ResultsData = Results.data();8167for (unsigned I = 0, N = Results.size(); I != N; ++I) {8168Result &R = ResultsData[I];8169if (R.Kind == Result::RK_Declaration &&8170isa<ObjCMethodDecl>(R.Declaration)) {8171if (R.Priority <= BestPriority) {8172const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);8173if (NumSelIdents <= Method->param_size()) {8174QualType MyPreferredType =8175Method->parameters()[NumSelIdents - 1]->getType();8176if (R.Priority < BestPriority || PreferredType.isNull()) {8177BestPriority = R.Priority;8178PreferredType = MyPreferredType;8179} else if (!Context.hasSameUnqualifiedType(PreferredType,8180MyPreferredType)) {8181PreferredType = QualType();8182}8183}8184}8185}8186}81878188return PreferredType;8189}81908191static void8192AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver,8193ArrayRef<const IdentifierInfo *> SelIdents,8194bool AtArgumentExpression, bool IsSuper,8195ResultBuilder &Results) {8196typedef CodeCompletionResult Result;8197ObjCInterfaceDecl *CDecl = nullptr;81988199// If the given name refers to an interface type, retrieve the8200// corresponding declaration.8201if (Receiver) {8202QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);8203if (!T.isNull())8204if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())8205CDecl = Interface->getInterface();8206}82078208// Add all of the factory methods in this Objective-C class, its protocols,8209// superclasses, categories, implementation, etc.8210Results.EnterNewScope();82118212// If this is a send-to-super, try to add the special "super" send8213// completion.8214if (IsSuper) {8215if (ObjCMethodDecl *SuperMethod =8216AddSuperSendCompletion(SemaRef, false, SelIdents, Results))8217Results.Ignore(SuperMethod);8218}82198220// If we're inside an Objective-C method definition, prefer its selector to8221// others.8222if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())8223Results.setPreferredSelector(CurMethod->getSelector());82248225VisitedSelectorSet Selectors;8226if (CDecl)8227AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,8228Selectors, AtArgumentExpression, Results);8229else {8230// We're messaging "id" as a type; provide all class/factory methods.82318232// If we have an external source, load the entire class method8233// pool from the AST file.8234if (SemaRef.getExternalSource()) {8235for (uint32_t I = 0,8236N = SemaRef.getExternalSource()->GetNumExternalSelectors();8237I != N; ++I) {8238Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);8239if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel))8240continue;82418242SemaRef.ObjC().ReadMethodPool(Sel);8243}8244}82458246for (SemaObjC::GlobalMethodPool::iterator8247M = SemaRef.ObjC().MethodPool.begin(),8248MEnd = SemaRef.ObjC().MethodPool.end();8249M != MEnd; ++M) {8250for (ObjCMethodList *MethList = &M->second.second;8251MethList && MethList->getMethod(); MethList = MethList->getNext()) {8252if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))8253continue;82548255Result R(MethList->getMethod(),8256Results.getBasePriority(MethList->getMethod()), nullptr);8257R.StartParameter = SelIdents.size();8258R.AllParametersAreInformative = false;8259Results.MaybeAddResult(R, SemaRef.CurContext);8260}8261}8262}82638264Results.ExitScope();8265}82668267void SemaCodeCompletion::CodeCompleteObjCClassMessage(8268Scope *S, ParsedType Receiver, ArrayRef<const IdentifierInfo *> SelIdents,8269bool AtArgumentExpression, bool IsSuper) {82708271QualType T = SemaRef.GetTypeFromParser(Receiver);82728273ResultBuilder Results(8274SemaRef, CodeCompleter->getAllocator(),8275CodeCompleter->getCodeCompletionTUInfo(),8276CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,8277SelIdents));82788279AddClassMessageCompletions(SemaRef, S, Receiver, SelIdents,8280AtArgumentExpression, IsSuper, Results);82818282// If we're actually at the argument expression (rather than prior to the8283// selector), we're actually performing code completion for an expression.8284// Determine whether we have a single, best method. If so, we can8285// code-complete the expression using the corresponding parameter type as8286// our preferred type, improving completion results.8287if (AtArgumentExpression) {8288QualType PreferredType =8289getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());8290if (PreferredType.isNull())8291CodeCompleteOrdinaryName(S, PCC_Expression);8292else8293CodeCompleteExpression(S, PreferredType);8294return;8295}82968297HandleCodeCompleteResults(&SemaRef, CodeCompleter,8298Results.getCompletionContext(), Results.data(),8299Results.size());8300}83018302void SemaCodeCompletion::CodeCompleteObjCInstanceMessage(8303Scope *S, Expr *Receiver, ArrayRef<const IdentifierInfo *> SelIdents,8304bool AtArgumentExpression, ObjCInterfaceDecl *Super) {8305typedef CodeCompletionResult Result;8306ASTContext &Context = getASTContext();83078308Expr *RecExpr = static_cast<Expr *>(Receiver);83098310// If necessary, apply function/array conversion to the receiver.8311// C99 6.7.5.3p[7,8].8312if (RecExpr) {8313ExprResult Conv = SemaRef.DefaultFunctionArrayLvalueConversion(RecExpr);8314if (Conv.isInvalid()) // conversion failed. bail.8315return;8316RecExpr = Conv.get();8317}8318QualType ReceiverType = RecExpr8319? RecExpr->getType()8320: Super ? Context.getObjCObjectPointerType(8321Context.getObjCInterfaceType(Super))8322: Context.getObjCIdType();83238324// If we're messaging an expression with type "id" or "Class", check8325// whether we know something special about the receiver that allows8326// us to assume a more-specific receiver type.8327if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {8328if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {8329if (ReceiverType->isObjCClassType())8330return CodeCompleteObjCClassMessage(8331S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,8332AtArgumentExpression, Super);83338334ReceiverType =8335Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));8336}8337} else if (RecExpr && getLangOpts().CPlusPlus) {8338ExprResult Conv = SemaRef.PerformContextuallyConvertToObjCPointer(RecExpr);8339if (Conv.isUsable()) {8340RecExpr = Conv.get();8341ReceiverType = RecExpr->getType();8342}8343}83448345// Build the set of methods we can see.8346ResultBuilder Results(8347SemaRef, CodeCompleter->getAllocator(),8348CodeCompleter->getCodeCompletionTUInfo(),8349CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,8350ReceiverType, SelIdents));83518352Results.EnterNewScope();83538354// If this is a send-to-super, try to add the special "super" send8355// completion.8356if (Super) {8357if (ObjCMethodDecl *SuperMethod =8358AddSuperSendCompletion(SemaRef, false, SelIdents, Results))8359Results.Ignore(SuperMethod);8360}83618362// If we're inside an Objective-C method definition, prefer its selector to8363// others.8364if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())8365Results.setPreferredSelector(CurMethod->getSelector());83668367// Keep track of the selectors we've already added.8368VisitedSelectorSet Selectors;83698370// Handle messages to Class. This really isn't a message to an instance8371// method, so we treat it the same way we would treat a message send to a8372// class method.8373if (ReceiverType->isObjCClassType() ||8374ReceiverType->isObjCQualifiedClassType()) {8375if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) {8376if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())8377AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, SemaRef.CurContext,8378Selectors, AtArgumentExpression, Results);8379}8380}8381// Handle messages to a qualified ID ("id<foo>").8382else if (const ObjCObjectPointerType *QualID =8383ReceiverType->getAsObjCQualifiedIdType()) {8384// Search protocols for instance methods.8385for (auto *I : QualID->quals())8386AddObjCMethods(I, true, MK_Any, SelIdents, SemaRef.CurContext, Selectors,8387AtArgumentExpression, Results);8388}8389// Handle messages to a pointer to interface type.8390else if (const ObjCObjectPointerType *IFacePtr =8391ReceiverType->getAsObjCInterfacePointerType()) {8392// Search the class, its superclasses, etc., for instance methods.8393AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,8394SemaRef.CurContext, Selectors, AtArgumentExpression,8395Results);83968397// Search protocols for instance methods.8398for (auto *I : IFacePtr->quals())8399AddObjCMethods(I, true, MK_Any, SelIdents, SemaRef.CurContext, Selectors,8400AtArgumentExpression, Results);8401}8402// Handle messages to "id".8403else if (ReceiverType->isObjCIdType()) {8404// We're messaging "id", so provide all instance methods we know8405// about as code-completion results.84068407// If we have an external source, load the entire class method8408// pool from the AST file.8409if (SemaRef.ExternalSource) {8410for (uint32_t I = 0,8411N = SemaRef.ExternalSource->GetNumExternalSelectors();8412I != N; ++I) {8413Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);8414if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel))8415continue;84168417SemaRef.ObjC().ReadMethodPool(Sel);8418}8419}84208421for (SemaObjC::GlobalMethodPool::iterator8422M = SemaRef.ObjC().MethodPool.begin(),8423MEnd = SemaRef.ObjC().MethodPool.end();8424M != MEnd; ++M) {8425for (ObjCMethodList *MethList = &M->second.first;8426MethList && MethList->getMethod(); MethList = MethList->getNext()) {8427if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))8428continue;84298430if (!Selectors.insert(MethList->getMethod()->getSelector()).second)8431continue;84328433Result R(MethList->getMethod(),8434Results.getBasePriority(MethList->getMethod()), nullptr);8435R.StartParameter = SelIdents.size();8436R.AllParametersAreInformative = false;8437Results.MaybeAddResult(R, SemaRef.CurContext);8438}8439}8440}8441Results.ExitScope();84428443// If we're actually at the argument expression (rather than prior to the8444// selector), we're actually performing code completion for an expression.8445// Determine whether we have a single, best method. If so, we can8446// code-complete the expression using the corresponding parameter type as8447// our preferred type, improving completion results.8448if (AtArgumentExpression) {8449QualType PreferredType =8450getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());8451if (PreferredType.isNull())8452CodeCompleteOrdinaryName(S, PCC_Expression);8453else8454CodeCompleteExpression(S, PreferredType);8455return;8456}84578458HandleCodeCompleteResults(&SemaRef, CodeCompleter,8459Results.getCompletionContext(), Results.data(),8460Results.size());8461}84628463void SemaCodeCompletion::CodeCompleteObjCForCollection(8464Scope *S, DeclGroupPtrTy IterationVar) {8465CodeCompleteExpressionData Data;8466Data.ObjCCollection = true;84678468if (IterationVar.getAsOpaquePtr()) {8469DeclGroupRef DG = IterationVar.get();8470for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {8471if (*I)8472Data.IgnoreDecls.push_back(*I);8473}8474}84758476CodeCompleteExpression(S, Data);8477}84788479void SemaCodeCompletion::CodeCompleteObjCSelector(8480Scope *S, ArrayRef<const IdentifierInfo *> SelIdents) {8481// If we have an external source, load the entire class method8482// pool from the AST file.8483if (SemaRef.ExternalSource) {8484for (uint32_t I = 0, N = SemaRef.ExternalSource->GetNumExternalSelectors();8485I != N; ++I) {8486Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);8487if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel))8488continue;84898490SemaRef.ObjC().ReadMethodPool(Sel);8491}8492}84938494ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8495CodeCompleter->getCodeCompletionTUInfo(),8496CodeCompletionContext::CCC_SelectorName);8497Results.EnterNewScope();8498for (SemaObjC::GlobalMethodPool::iterator8499M = SemaRef.ObjC().MethodPool.begin(),8500MEnd = SemaRef.ObjC().MethodPool.end();8501M != MEnd; ++M) {85028503Selector Sel = M->first;8504if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))8505continue;85068507CodeCompletionBuilder Builder(Results.getAllocator(),8508Results.getCodeCompletionTUInfo());8509if (Sel.isUnarySelector()) {8510Builder.AddTypedTextChunk(8511Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));8512Results.AddResult(Builder.TakeString());8513continue;8514}85158516std::string Accumulator;8517for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {8518if (I == SelIdents.size()) {8519if (!Accumulator.empty()) {8520Builder.AddInformativeChunk(8521Builder.getAllocator().CopyString(Accumulator));8522Accumulator.clear();8523}8524}85258526Accumulator += Sel.getNameForSlot(I);8527Accumulator += ':';8528}8529Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));8530Results.AddResult(Builder.TakeString());8531}8532Results.ExitScope();85338534HandleCodeCompleteResults(&SemaRef, CodeCompleter,8535Results.getCompletionContext(), Results.data(),8536Results.size());8537}85388539/// Add all of the protocol declarations that we find in the given8540/// (translation unit) context.8541static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,8542bool OnlyForwardDeclarations,8543ResultBuilder &Results) {8544typedef CodeCompletionResult Result;85458546for (const auto *D : Ctx->decls()) {8547// Record any protocols we find.8548if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))8549if (!OnlyForwardDeclarations || !Proto->hasDefinition())8550Results.AddResult(8551Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,8552nullptr, false);8553}8554}85558556void SemaCodeCompletion::CodeCompleteObjCProtocolReferences(8557ArrayRef<IdentifierLocPair> Protocols) {8558ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8559CodeCompleter->getCodeCompletionTUInfo(),8560CodeCompletionContext::CCC_ObjCProtocolName);85618562if (CodeCompleter->includeGlobals()) {8563Results.EnterNewScope();85648565// Tell the result set to ignore all of the protocols we have8566// already seen.8567// FIXME: This doesn't work when caching code-completion results.8568for (const IdentifierLocPair &Pair : Protocols)8569if (ObjCProtocolDecl *Protocol =8570SemaRef.ObjC().LookupProtocol(Pair.first, Pair.second))8571Results.Ignore(Protocol);85728573// Add all protocols.8574AddProtocolResults(getASTContext().getTranslationUnitDecl(),8575SemaRef.CurContext, false, Results);85768577Results.ExitScope();8578}85798580HandleCodeCompleteResults(&SemaRef, CodeCompleter,8581Results.getCompletionContext(), Results.data(),8582Results.size());8583}85848585void SemaCodeCompletion::CodeCompleteObjCProtocolDecl(Scope *) {8586ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8587CodeCompleter->getCodeCompletionTUInfo(),8588CodeCompletionContext::CCC_ObjCProtocolName);85898590if (CodeCompleter->includeGlobals()) {8591Results.EnterNewScope();85928593// Add all protocols.8594AddProtocolResults(getASTContext().getTranslationUnitDecl(),8595SemaRef.CurContext, true, Results);85968597Results.ExitScope();8598}85998600HandleCodeCompleteResults(&SemaRef, CodeCompleter,8601Results.getCompletionContext(), Results.data(),8602Results.size());8603}86048605/// Add all of the Objective-C interface declarations that we find in8606/// the given (translation unit) context.8607static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,8608bool OnlyForwardDeclarations,8609bool OnlyUnimplemented,8610ResultBuilder &Results) {8611typedef CodeCompletionResult Result;86128613for (const auto *D : Ctx->decls()) {8614// Record any interfaces we find.8615if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))8616if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&8617(!OnlyUnimplemented || !Class->getImplementation()))8618Results.AddResult(8619Result(Class, Results.getBasePriority(Class), nullptr), CurContext,8620nullptr, false);8621}8622}86238624void SemaCodeCompletion::CodeCompleteObjCInterfaceDecl(Scope *S) {8625ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8626CodeCompleter->getCodeCompletionTUInfo(),8627CodeCompletionContext::CCC_ObjCInterfaceName);8628Results.EnterNewScope();86298630if (CodeCompleter->includeGlobals()) {8631// Add all classes.8632AddInterfaceResults(getASTContext().getTranslationUnitDecl(),8633SemaRef.CurContext, false, false, Results);8634}86358636Results.ExitScope();86378638HandleCodeCompleteResults(&SemaRef, CodeCompleter,8639Results.getCompletionContext(), Results.data(),8640Results.size());8641}86428643void SemaCodeCompletion::CodeCompleteObjCClassForwardDecl(Scope *S) {8644ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8645CodeCompleter->getCodeCompletionTUInfo(),8646CodeCompletionContext::CCC_ObjCClassForwardDecl);8647Results.EnterNewScope();86488649if (CodeCompleter->includeGlobals()) {8650// Add all classes.8651AddInterfaceResults(getASTContext().getTranslationUnitDecl(),8652SemaRef.CurContext, false, false, Results);8653}86548655Results.ExitScope();86568657HandleCodeCompleteResults(&SemaRef, CodeCompleter,8658Results.getCompletionContext(), Results.data(),8659Results.size());8660}86618662void SemaCodeCompletion::CodeCompleteObjCSuperclass(8663Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) {8664ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8665CodeCompleter->getCodeCompletionTUInfo(),8666CodeCompletionContext::CCC_ObjCInterfaceName);8667Results.EnterNewScope();86688669// Make sure that we ignore the class we're currently defining.8670NamedDecl *CurClass = SemaRef.LookupSingleName(8671SemaRef.TUScope, ClassName, ClassNameLoc, Sema::LookupOrdinaryName);8672if (CurClass && isa<ObjCInterfaceDecl>(CurClass))8673Results.Ignore(CurClass);86748675if (CodeCompleter->includeGlobals()) {8676// Add all classes.8677AddInterfaceResults(getASTContext().getTranslationUnitDecl(),8678SemaRef.CurContext, false, false, Results);8679}86808681Results.ExitScope();86828683HandleCodeCompleteResults(&SemaRef, CodeCompleter,8684Results.getCompletionContext(), Results.data(),8685Results.size());8686}86878688void SemaCodeCompletion::CodeCompleteObjCImplementationDecl(Scope *S) {8689ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8690CodeCompleter->getCodeCompletionTUInfo(),8691CodeCompletionContext::CCC_ObjCImplementation);8692Results.EnterNewScope();86938694if (CodeCompleter->includeGlobals()) {8695// Add all unimplemented classes.8696AddInterfaceResults(getASTContext().getTranslationUnitDecl(),8697SemaRef.CurContext, false, true, Results);8698}86998700Results.ExitScope();87018702HandleCodeCompleteResults(&SemaRef, CodeCompleter,8703Results.getCompletionContext(), Results.data(),8704Results.size());8705}87068707void SemaCodeCompletion::CodeCompleteObjCInterfaceCategory(8708Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) {8709typedef CodeCompletionResult Result;87108711ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8712CodeCompleter->getCodeCompletionTUInfo(),8713CodeCompletionContext::CCC_ObjCCategoryName);87148715// Ignore any categories we find that have already been implemented by this8716// interface.8717llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;8718NamedDecl *CurClass = SemaRef.LookupSingleName(8719SemaRef.TUScope, ClassName, ClassNameLoc, Sema::LookupOrdinaryName);8720if (ObjCInterfaceDecl *Class =8721dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {8722for (const auto *Cat : Class->visible_categories())8723CategoryNames.insert(Cat->getIdentifier());8724}87258726// Add all of the categories we know about.8727Results.EnterNewScope();8728TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();8729for (const auto *D : TU->decls())8730if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))8731if (CategoryNames.insert(Category->getIdentifier()).second)8732Results.AddResult(8733Result(Category, Results.getBasePriority(Category), nullptr),8734SemaRef.CurContext, nullptr, false);8735Results.ExitScope();87368737HandleCodeCompleteResults(&SemaRef, CodeCompleter,8738Results.getCompletionContext(), Results.data(),8739Results.size());8740}87418742void SemaCodeCompletion::CodeCompleteObjCImplementationCategory(8743Scope *S, IdentifierInfo *ClassName, SourceLocation ClassNameLoc) {8744typedef CodeCompletionResult Result;87458746// Find the corresponding interface. If we couldn't find the interface, the8747// program itself is ill-formed. However, we'll try to be helpful still by8748// providing the list of all of the categories we know about.8749NamedDecl *CurClass = SemaRef.LookupSingleName(8750SemaRef.TUScope, ClassName, ClassNameLoc, Sema::LookupOrdinaryName);8751ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);8752if (!Class)8753return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);87548755ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8756CodeCompleter->getCodeCompletionTUInfo(),8757CodeCompletionContext::CCC_ObjCCategoryName);87588759// Add all of the categories that have corresponding interface8760// declarations in this class and any of its superclasses, except for8761// already-implemented categories in the class itself.8762llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;8763Results.EnterNewScope();8764bool IgnoreImplemented = true;8765while (Class) {8766for (const auto *Cat : Class->visible_categories()) {8767if ((!IgnoreImplemented || !Cat->getImplementation()) &&8768CategoryNames.insert(Cat->getIdentifier()).second)8769Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),8770SemaRef.CurContext, nullptr, false);8771}87728773Class = Class->getSuperClass();8774IgnoreImplemented = false;8775}8776Results.ExitScope();87778778HandleCodeCompleteResults(&SemaRef, CodeCompleter,8779Results.getCompletionContext(), Results.data(),8780Results.size());8781}87828783void SemaCodeCompletion::CodeCompleteObjCPropertyDefinition(Scope *S) {8784CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);8785ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8786CodeCompleter->getCodeCompletionTUInfo(), CCContext);87878788// Figure out where this @synthesize lives.8789ObjCContainerDecl *Container =8790dyn_cast_or_null<ObjCContainerDecl>(SemaRef.CurContext);8791if (!Container || (!isa<ObjCImplementationDecl>(Container) &&8792!isa<ObjCCategoryImplDecl>(Container)))8793return;87948795// Ignore any properties that have already been implemented.8796Container = getContainerDef(Container);8797for (const auto *D : Container->decls())8798if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))8799Results.Ignore(PropertyImpl->getPropertyDecl());88008801// Add any properties that we find.8802AddedPropertiesSet AddedProperties;8803Results.EnterNewScope();8804if (ObjCImplementationDecl *ClassImpl =8805dyn_cast<ObjCImplementationDecl>(Container))8806AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,8807/*AllowNullaryMethods=*/false, SemaRef.CurContext,8808AddedProperties, Results);8809else8810AddObjCProperties(CCContext,8811cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),8812false, /*AllowNullaryMethods=*/false, SemaRef.CurContext,8813AddedProperties, Results);8814Results.ExitScope();88158816HandleCodeCompleteResults(&SemaRef, CodeCompleter,8817Results.getCompletionContext(), Results.data(),8818Results.size());8819}88208821void SemaCodeCompletion::CodeCompleteObjCPropertySynthesizeIvar(8822Scope *S, IdentifierInfo *PropertyName) {8823typedef CodeCompletionResult Result;8824ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),8825CodeCompleter->getCodeCompletionTUInfo(),8826CodeCompletionContext::CCC_Other);88278828// Figure out where this @synthesize lives.8829ObjCContainerDecl *Container =8830dyn_cast_or_null<ObjCContainerDecl>(SemaRef.CurContext);8831if (!Container || (!isa<ObjCImplementationDecl>(Container) &&8832!isa<ObjCCategoryImplDecl>(Container)))8833return;88348835// Figure out which interface we're looking into.8836ObjCInterfaceDecl *Class = nullptr;8837if (ObjCImplementationDecl *ClassImpl =8838dyn_cast<ObjCImplementationDecl>(Container))8839Class = ClassImpl->getClassInterface();8840else8841Class = cast<ObjCCategoryImplDecl>(Container)8842->getCategoryDecl()8843->getClassInterface();88448845// Determine the type of the property we're synthesizing.8846QualType PropertyType = getASTContext().getObjCIdType();8847if (Class) {8848if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(8849PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {8850PropertyType =8851Property->getType().getNonReferenceType().getUnqualifiedType();88528853// Give preference to ivars8854Results.setPreferredType(PropertyType);8855}8856}88578858// Add all of the instance variables in this class and its superclasses.8859Results.EnterNewScope();8860bool SawSimilarlyNamedIvar = false;8861std::string NameWithPrefix;8862NameWithPrefix += '_';8863NameWithPrefix += PropertyName->getName();8864std::string NameWithSuffix = PropertyName->getName().str();8865NameWithSuffix += '_';8866for (; Class; Class = Class->getSuperClass()) {8867for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;8868Ivar = Ivar->getNextIvar()) {8869Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),8870SemaRef.CurContext, nullptr, false);88718872// Determine whether we've seen an ivar with a name similar to the8873// property.8874if ((PropertyName == Ivar->getIdentifier() ||8875NameWithPrefix == Ivar->getName() ||8876NameWithSuffix == Ivar->getName())) {8877SawSimilarlyNamedIvar = true;88788879// Reduce the priority of this result by one, to give it a slight8880// advantage over other results whose names don't match so closely.8881if (Results.size() &&8882Results.data()[Results.size() - 1].Kind ==8883CodeCompletionResult::RK_Declaration &&8884Results.data()[Results.size() - 1].Declaration == Ivar)8885Results.data()[Results.size() - 1].Priority--;8886}8887}8888}88898890if (!SawSimilarlyNamedIvar) {8891// Create ivar result _propName, that the user can use to synthesize8892// an ivar of the appropriate type.8893unsigned Priority = CCP_MemberDeclaration + 1;8894typedef CodeCompletionResult Result;8895CodeCompletionAllocator &Allocator = Results.getAllocator();8896CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),8897Priority, CXAvailability_Available);88988899PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);8900Builder.AddResultTypeChunk(GetCompletionTypeString(8901PropertyType, getASTContext(), Policy, Allocator));8902Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));8903Results.AddResult(8904Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));8905}89068907Results.ExitScope();89088909HandleCodeCompleteResults(&SemaRef, CodeCompleter,8910Results.getCompletionContext(), Results.data(),8911Results.size());8912}89138914// Mapping from selectors to the methods that implement that selector, along8915// with the "in original class" flag.8916typedef llvm::DenseMap<Selector,8917llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>8918KnownMethodsMap;89198920/// Find all of the methods that reside in the given container8921/// (and its superclasses, protocols, etc.) that meet the given8922/// criteria. Insert those methods into the map of known methods,8923/// indexed by selector so they can be easily found.8924static void FindImplementableMethods(ASTContext &Context,8925ObjCContainerDecl *Container,8926std::optional<bool> WantInstanceMethods,8927QualType ReturnType,8928KnownMethodsMap &KnownMethods,8929bool InOriginalClass = true) {8930if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {8931// Make sure we have a definition; that's what we'll walk.8932if (!IFace->hasDefinition())8933return;89348935IFace = IFace->getDefinition();8936Container = IFace;89378938const ObjCList<ObjCProtocolDecl> &Protocols =8939IFace->getReferencedProtocols();8940for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),8941E = Protocols.end();8942I != E; ++I)8943FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,8944KnownMethods, InOriginalClass);89458946// Add methods from any class extensions and categories.8947for (auto *Cat : IFace->visible_categories()) {8948FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,8949KnownMethods, false);8950}89518952// Visit the superclass.8953if (IFace->getSuperClass())8954FindImplementableMethods(Context, IFace->getSuperClass(),8955WantInstanceMethods, ReturnType, KnownMethods,8956false);8957}89588959if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {8960// Recurse into protocols.8961const ObjCList<ObjCProtocolDecl> &Protocols =8962Category->getReferencedProtocols();8963for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),8964E = Protocols.end();8965I != E; ++I)8966FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,8967KnownMethods, InOriginalClass);89688969// If this category is the original class, jump to the interface.8970if (InOriginalClass && Category->getClassInterface())8971FindImplementableMethods(Context, Category->getClassInterface(),8972WantInstanceMethods, ReturnType, KnownMethods,8973false);8974}89758976if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {8977// Make sure we have a definition; that's what we'll walk.8978if (!Protocol->hasDefinition())8979return;8980Protocol = Protocol->getDefinition();8981Container = Protocol;89828983// Recurse into protocols.8984const ObjCList<ObjCProtocolDecl> &Protocols =8985Protocol->getReferencedProtocols();8986for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),8987E = Protocols.end();8988I != E; ++I)8989FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,8990KnownMethods, false);8991}89928993// Add methods in this container. This operation occurs last because8994// we want the methods from this container to override any methods8995// we've previously seen with the same selector.8996for (auto *M : Container->methods()) {8997if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {8998if (!ReturnType.isNull() &&8999!Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))9000continue;90019002KnownMethods[M->getSelector()] =9003KnownMethodsMap::mapped_type(M, InOriginalClass);9004}9005}9006}90079008/// Add the parenthesized return or parameter type chunk to a code9009/// completion string.9010static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,9011ASTContext &Context,9012const PrintingPolicy &Policy,9013CodeCompletionBuilder &Builder) {9014Builder.AddChunk(CodeCompletionString::CK_LeftParen);9015std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);9016if (!Quals.empty())9017Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));9018Builder.AddTextChunk(9019GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));9020Builder.AddChunk(CodeCompletionString::CK_RightParen);9021}90229023/// Determine whether the given class is or inherits from a class by9024/// the given name.9025static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {9026if (!Class)9027return false;90289029if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)9030return true;90319032return InheritsFromClassNamed(Class->getSuperClass(), Name);9033}90349035/// Add code completions for Objective-C Key-Value Coding (KVC) and9036/// Key-Value Observing (KVO).9037static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,9038bool IsInstanceMethod,9039QualType ReturnType, ASTContext &Context,9040VisitedSelectorSet &KnownSelectors,9041ResultBuilder &Results) {9042IdentifierInfo *PropName = Property->getIdentifier();9043if (!PropName || PropName->getLength() == 0)9044return;90459046PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());90479048// Builder that will create each code completion.9049typedef CodeCompletionResult Result;9050CodeCompletionAllocator &Allocator = Results.getAllocator();9051CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());90529053// The selector table.9054SelectorTable &Selectors = Context.Selectors;90559056// The property name, copied into the code completion allocation region9057// on demand.9058struct KeyHolder {9059CodeCompletionAllocator &Allocator;9060StringRef Key;9061const char *CopiedKey;90629063KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)9064: Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}90659066operator const char *() {9067if (CopiedKey)9068return CopiedKey;90699070return CopiedKey = Allocator.CopyString(Key);9071}9072} Key(Allocator, PropName->getName());90739074// The uppercased name of the property name.9075std::string UpperKey = std::string(PropName->getName());9076if (!UpperKey.empty())9077UpperKey[0] = toUppercase(UpperKey[0]);90789079bool ReturnTypeMatchesProperty =9080ReturnType.isNull() ||9081Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),9082Property->getType());9083bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();90849085// Add the normal accessor -(type)key.9086if (IsInstanceMethod &&9087KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&9088ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {9089if (ReturnType.isNull())9090AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,9091Builder);90929093Builder.AddTypedTextChunk(Key);9094Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,9095CXCursor_ObjCInstanceMethodDecl));9096}90979098// If we have an integral or boolean property (or the user has provided9099// an integral or boolean return type), add the accessor -(type)isKey.9100if (IsInstanceMethod &&9101((!ReturnType.isNull() &&9102(ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||9103(ReturnType.isNull() && (Property->getType()->isIntegerType() ||9104Property->getType()->isBooleanType())))) {9105std::string SelectorName = (Twine("is") + UpperKey).str();9106IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9107if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))9108.second) {9109if (ReturnType.isNull()) {9110Builder.AddChunk(CodeCompletionString::CK_LeftParen);9111Builder.AddTextChunk("BOOL");9112Builder.AddChunk(CodeCompletionString::CK_RightParen);9113}91149115Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));9116Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,9117CXCursor_ObjCInstanceMethodDecl));9118}9119}91209121// Add the normal mutator.9122if (IsInstanceMethod && ReturnTypeMatchesVoid &&9123!Property->getSetterMethodDecl()) {9124std::string SelectorName = (Twine("set") + UpperKey).str();9125IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9126if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9127if (ReturnType.isNull()) {9128Builder.AddChunk(CodeCompletionString::CK_LeftParen);9129Builder.AddTextChunk("void");9130Builder.AddChunk(CodeCompletionString::CK_RightParen);9131}91329133Builder.AddTypedTextChunk(9134Allocator.CopyString(SelectorId->getName() + ":"));9135AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,9136Builder);9137Builder.AddTextChunk(Key);9138Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,9139CXCursor_ObjCInstanceMethodDecl));9140}9141}91429143// Indexed and unordered accessors9144unsigned IndexedGetterPriority = CCP_CodePattern;9145unsigned IndexedSetterPriority = CCP_CodePattern;9146unsigned UnorderedGetterPriority = CCP_CodePattern;9147unsigned UnorderedSetterPriority = CCP_CodePattern;9148if (const auto *ObjCPointer =9149Property->getType()->getAs<ObjCObjectPointerType>()) {9150if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {9151// If this interface type is not provably derived from a known9152// collection, penalize the corresponding completions.9153if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {9154IndexedSetterPriority += CCD_ProbablyNotObjCCollection;9155if (!InheritsFromClassNamed(IFace, "NSArray"))9156IndexedGetterPriority += CCD_ProbablyNotObjCCollection;9157}91589159if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {9160UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;9161if (!InheritsFromClassNamed(IFace, "NSSet"))9162UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;9163}9164}9165} else {9166IndexedGetterPriority += CCD_ProbablyNotObjCCollection;9167IndexedSetterPriority += CCD_ProbablyNotObjCCollection;9168UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;9169UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;9170}91719172// Add -(NSUInteger)countOf<key>9173if (IsInstanceMethod &&9174(ReturnType.isNull() || ReturnType->isIntegerType())) {9175std::string SelectorName = (Twine("countOf") + UpperKey).str();9176IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9177if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))9178.second) {9179if (ReturnType.isNull()) {9180Builder.AddChunk(CodeCompletionString::CK_LeftParen);9181Builder.AddTextChunk("NSUInteger");9182Builder.AddChunk(CodeCompletionString::CK_RightParen);9183}91849185Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));9186Results.AddResult(9187Result(Builder.TakeString(),9188std::min(IndexedGetterPriority, UnorderedGetterPriority),9189CXCursor_ObjCInstanceMethodDecl));9190}9191}91929193// Indexed getters9194// Add -(id)objectInKeyAtIndex:(NSUInteger)index9195if (IsInstanceMethod &&9196(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {9197std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();9198IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9199if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9200if (ReturnType.isNull()) {9201Builder.AddChunk(CodeCompletionString::CK_LeftParen);9202Builder.AddTextChunk("id");9203Builder.AddChunk(CodeCompletionString::CK_RightParen);9204}92059206Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9207Builder.AddChunk(CodeCompletionString::CK_LeftParen);9208Builder.AddTextChunk("NSUInteger");9209Builder.AddChunk(CodeCompletionString::CK_RightParen);9210Builder.AddTextChunk("index");9211Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,9212CXCursor_ObjCInstanceMethodDecl));9213}9214}92159216// Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes9217if (IsInstanceMethod &&9218(ReturnType.isNull() ||9219(ReturnType->isObjCObjectPointerType() &&9220ReturnType->castAs<ObjCObjectPointerType>()->getInterfaceDecl() &&9221ReturnType->castAs<ObjCObjectPointerType>()9222->getInterfaceDecl()9223->getName() == "NSArray"))) {9224std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();9225IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9226if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9227if (ReturnType.isNull()) {9228Builder.AddChunk(CodeCompletionString::CK_LeftParen);9229Builder.AddTextChunk("NSArray *");9230Builder.AddChunk(CodeCompletionString::CK_RightParen);9231}92329233Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9234Builder.AddChunk(CodeCompletionString::CK_LeftParen);9235Builder.AddTextChunk("NSIndexSet *");9236Builder.AddChunk(CodeCompletionString::CK_RightParen);9237Builder.AddTextChunk("indexes");9238Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,9239CXCursor_ObjCInstanceMethodDecl));9240}9241}92429243// Add -(void)getKey:(type **)buffer range:(NSRange)inRange9244if (IsInstanceMethod && ReturnTypeMatchesVoid) {9245std::string SelectorName = (Twine("get") + UpperKey).str();9246const IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),9247&Context.Idents.get("range")};92489249if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {9250if (ReturnType.isNull()) {9251Builder.AddChunk(CodeCompletionString::CK_LeftParen);9252Builder.AddTextChunk("void");9253Builder.AddChunk(CodeCompletionString::CK_RightParen);9254}92559256Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9257Builder.AddChunk(CodeCompletionString::CK_LeftParen);9258Builder.AddPlaceholderChunk("object-type");9259Builder.AddTextChunk(" **");9260Builder.AddChunk(CodeCompletionString::CK_RightParen);9261Builder.AddTextChunk("buffer");9262Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9263Builder.AddTypedTextChunk("range:");9264Builder.AddChunk(CodeCompletionString::CK_LeftParen);9265Builder.AddTextChunk("NSRange");9266Builder.AddChunk(CodeCompletionString::CK_RightParen);9267Builder.AddTextChunk("inRange");9268Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,9269CXCursor_ObjCInstanceMethodDecl));9270}9271}92729273// Mutable indexed accessors92749275// - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index9276if (IsInstanceMethod && ReturnTypeMatchesVoid) {9277std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();9278const IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),9279&Context.Idents.get(SelectorName)};92809281if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {9282if (ReturnType.isNull()) {9283Builder.AddChunk(CodeCompletionString::CK_LeftParen);9284Builder.AddTextChunk("void");9285Builder.AddChunk(CodeCompletionString::CK_RightParen);9286}92879288Builder.AddTypedTextChunk("insertObject:");9289Builder.AddChunk(CodeCompletionString::CK_LeftParen);9290Builder.AddPlaceholderChunk("object-type");9291Builder.AddTextChunk(" *");9292Builder.AddChunk(CodeCompletionString::CK_RightParen);9293Builder.AddTextChunk("object");9294Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9295Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9296Builder.AddChunk(CodeCompletionString::CK_LeftParen);9297Builder.AddPlaceholderChunk("NSUInteger");9298Builder.AddChunk(CodeCompletionString::CK_RightParen);9299Builder.AddTextChunk("index");9300Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,9301CXCursor_ObjCInstanceMethodDecl));9302}9303}93049305// - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes9306if (IsInstanceMethod && ReturnTypeMatchesVoid) {9307std::string SelectorName = (Twine("insert") + UpperKey).str();9308const IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),9309&Context.Idents.get("atIndexes")};93109311if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {9312if (ReturnType.isNull()) {9313Builder.AddChunk(CodeCompletionString::CK_LeftParen);9314Builder.AddTextChunk("void");9315Builder.AddChunk(CodeCompletionString::CK_RightParen);9316}93179318Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9319Builder.AddChunk(CodeCompletionString::CK_LeftParen);9320Builder.AddTextChunk("NSArray *");9321Builder.AddChunk(CodeCompletionString::CK_RightParen);9322Builder.AddTextChunk("array");9323Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9324Builder.AddTypedTextChunk("atIndexes:");9325Builder.AddChunk(CodeCompletionString::CK_LeftParen);9326Builder.AddPlaceholderChunk("NSIndexSet *");9327Builder.AddChunk(CodeCompletionString::CK_RightParen);9328Builder.AddTextChunk("indexes");9329Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,9330CXCursor_ObjCInstanceMethodDecl));9331}9332}93339334// -(void)removeObjectFromKeyAtIndex:(NSUInteger)index9335if (IsInstanceMethod && ReturnTypeMatchesVoid) {9336std::string SelectorName =9337(Twine("removeObjectFrom") + UpperKey + "AtIndex").str();9338const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9339if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9340if (ReturnType.isNull()) {9341Builder.AddChunk(CodeCompletionString::CK_LeftParen);9342Builder.AddTextChunk("void");9343Builder.AddChunk(CodeCompletionString::CK_RightParen);9344}93459346Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9347Builder.AddChunk(CodeCompletionString::CK_LeftParen);9348Builder.AddTextChunk("NSUInteger");9349Builder.AddChunk(CodeCompletionString::CK_RightParen);9350Builder.AddTextChunk("index");9351Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,9352CXCursor_ObjCInstanceMethodDecl));9353}9354}93559356// -(void)removeKeyAtIndexes:(NSIndexSet *)indexes9357if (IsInstanceMethod && ReturnTypeMatchesVoid) {9358std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();9359const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9360if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9361if (ReturnType.isNull()) {9362Builder.AddChunk(CodeCompletionString::CK_LeftParen);9363Builder.AddTextChunk("void");9364Builder.AddChunk(CodeCompletionString::CK_RightParen);9365}93669367Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9368Builder.AddChunk(CodeCompletionString::CK_LeftParen);9369Builder.AddTextChunk("NSIndexSet *");9370Builder.AddChunk(CodeCompletionString::CK_RightParen);9371Builder.AddTextChunk("indexes");9372Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,9373CXCursor_ObjCInstanceMethodDecl));9374}9375}93769377// - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object9378if (IsInstanceMethod && ReturnTypeMatchesVoid) {9379std::string SelectorName =9380(Twine("replaceObjectIn") + UpperKey + "AtIndex").str();9381const IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),9382&Context.Idents.get("withObject")};93839384if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {9385if (ReturnType.isNull()) {9386Builder.AddChunk(CodeCompletionString::CK_LeftParen);9387Builder.AddTextChunk("void");9388Builder.AddChunk(CodeCompletionString::CK_RightParen);9389}93909391Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9392Builder.AddChunk(CodeCompletionString::CK_LeftParen);9393Builder.AddPlaceholderChunk("NSUInteger");9394Builder.AddChunk(CodeCompletionString::CK_RightParen);9395Builder.AddTextChunk("index");9396Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9397Builder.AddTypedTextChunk("withObject:");9398Builder.AddChunk(CodeCompletionString::CK_LeftParen);9399Builder.AddTextChunk("id");9400Builder.AddChunk(CodeCompletionString::CK_RightParen);9401Builder.AddTextChunk("object");9402Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,9403CXCursor_ObjCInstanceMethodDecl));9404}9405}94069407// - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array9408if (IsInstanceMethod && ReturnTypeMatchesVoid) {9409std::string SelectorName1 =9410(Twine("replace") + UpperKey + "AtIndexes").str();9411std::string SelectorName2 = (Twine("with") + UpperKey).str();9412const IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),9413&Context.Idents.get(SelectorName2)};94149415if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {9416if (ReturnType.isNull()) {9417Builder.AddChunk(CodeCompletionString::CK_LeftParen);9418Builder.AddTextChunk("void");9419Builder.AddChunk(CodeCompletionString::CK_RightParen);9420}94219422Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));9423Builder.AddChunk(CodeCompletionString::CK_LeftParen);9424Builder.AddPlaceholderChunk("NSIndexSet *");9425Builder.AddChunk(CodeCompletionString::CK_RightParen);9426Builder.AddTextChunk("indexes");9427Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9428Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));9429Builder.AddChunk(CodeCompletionString::CK_LeftParen);9430Builder.AddTextChunk("NSArray *");9431Builder.AddChunk(CodeCompletionString::CK_RightParen);9432Builder.AddTextChunk("array");9433Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,9434CXCursor_ObjCInstanceMethodDecl));9435}9436}94379438// Unordered getters9439// - (NSEnumerator *)enumeratorOfKey9440if (IsInstanceMethod &&9441(ReturnType.isNull() ||9442(ReturnType->isObjCObjectPointerType() &&9443ReturnType->castAs<ObjCObjectPointerType>()->getInterfaceDecl() &&9444ReturnType->castAs<ObjCObjectPointerType>()9445->getInterfaceDecl()9446->getName() == "NSEnumerator"))) {9447std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();9448const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9449if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))9450.second) {9451if (ReturnType.isNull()) {9452Builder.AddChunk(CodeCompletionString::CK_LeftParen);9453Builder.AddTextChunk("NSEnumerator *");9454Builder.AddChunk(CodeCompletionString::CK_RightParen);9455}94569457Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));9458Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,9459CXCursor_ObjCInstanceMethodDecl));9460}9461}94629463// - (type *)memberOfKey:(type *)object9464if (IsInstanceMethod &&9465(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {9466std::string SelectorName = (Twine("memberOf") + UpperKey).str();9467const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9468if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9469if (ReturnType.isNull()) {9470Builder.AddChunk(CodeCompletionString::CK_LeftParen);9471Builder.AddPlaceholderChunk("object-type");9472Builder.AddTextChunk(" *");9473Builder.AddChunk(CodeCompletionString::CK_RightParen);9474}94759476Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9477Builder.AddChunk(CodeCompletionString::CK_LeftParen);9478if (ReturnType.isNull()) {9479Builder.AddPlaceholderChunk("object-type");9480Builder.AddTextChunk(" *");9481} else {9482Builder.AddTextChunk(GetCompletionTypeString(9483ReturnType, Context, Policy, Builder.getAllocator()));9484}9485Builder.AddChunk(CodeCompletionString::CK_RightParen);9486Builder.AddTextChunk("object");9487Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,9488CXCursor_ObjCInstanceMethodDecl));9489}9490}94919492// Mutable unordered accessors9493// - (void)addKeyObject:(type *)object9494if (IsInstanceMethod && ReturnTypeMatchesVoid) {9495std::string SelectorName =9496(Twine("add") + UpperKey + Twine("Object")).str();9497const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9498if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9499if (ReturnType.isNull()) {9500Builder.AddChunk(CodeCompletionString::CK_LeftParen);9501Builder.AddTextChunk("void");9502Builder.AddChunk(CodeCompletionString::CK_RightParen);9503}95049505Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9506Builder.AddChunk(CodeCompletionString::CK_LeftParen);9507Builder.AddPlaceholderChunk("object-type");9508Builder.AddTextChunk(" *");9509Builder.AddChunk(CodeCompletionString::CK_RightParen);9510Builder.AddTextChunk("object");9511Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,9512CXCursor_ObjCInstanceMethodDecl));9513}9514}95159516// - (void)addKey:(NSSet *)objects9517if (IsInstanceMethod && ReturnTypeMatchesVoid) {9518std::string SelectorName = (Twine("add") + UpperKey).str();9519const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9520if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9521if (ReturnType.isNull()) {9522Builder.AddChunk(CodeCompletionString::CK_LeftParen);9523Builder.AddTextChunk("void");9524Builder.AddChunk(CodeCompletionString::CK_RightParen);9525}95269527Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9528Builder.AddChunk(CodeCompletionString::CK_LeftParen);9529Builder.AddTextChunk("NSSet *");9530Builder.AddChunk(CodeCompletionString::CK_RightParen);9531Builder.AddTextChunk("objects");9532Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,9533CXCursor_ObjCInstanceMethodDecl));9534}9535}95369537// - (void)removeKeyObject:(type *)object9538if (IsInstanceMethod && ReturnTypeMatchesVoid) {9539std::string SelectorName =9540(Twine("remove") + UpperKey + Twine("Object")).str();9541const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9542if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9543if (ReturnType.isNull()) {9544Builder.AddChunk(CodeCompletionString::CK_LeftParen);9545Builder.AddTextChunk("void");9546Builder.AddChunk(CodeCompletionString::CK_RightParen);9547}95489549Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9550Builder.AddChunk(CodeCompletionString::CK_LeftParen);9551Builder.AddPlaceholderChunk("object-type");9552Builder.AddTextChunk(" *");9553Builder.AddChunk(CodeCompletionString::CK_RightParen);9554Builder.AddTextChunk("object");9555Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,9556CXCursor_ObjCInstanceMethodDecl));9557}9558}95599560// - (void)removeKey:(NSSet *)objects9561if (IsInstanceMethod && ReturnTypeMatchesVoid) {9562std::string SelectorName = (Twine("remove") + UpperKey).str();9563const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9564if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9565if (ReturnType.isNull()) {9566Builder.AddChunk(CodeCompletionString::CK_LeftParen);9567Builder.AddTextChunk("void");9568Builder.AddChunk(CodeCompletionString::CK_RightParen);9569}95709571Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9572Builder.AddChunk(CodeCompletionString::CK_LeftParen);9573Builder.AddTextChunk("NSSet *");9574Builder.AddChunk(CodeCompletionString::CK_RightParen);9575Builder.AddTextChunk("objects");9576Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,9577CXCursor_ObjCInstanceMethodDecl));9578}9579}95809581// - (void)intersectKey:(NSSet *)objects9582if (IsInstanceMethod && ReturnTypeMatchesVoid) {9583std::string SelectorName = (Twine("intersect") + UpperKey).str();9584const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9585if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {9586if (ReturnType.isNull()) {9587Builder.AddChunk(CodeCompletionString::CK_LeftParen);9588Builder.AddTextChunk("void");9589Builder.AddChunk(CodeCompletionString::CK_RightParen);9590}95919592Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));9593Builder.AddChunk(CodeCompletionString::CK_LeftParen);9594Builder.AddTextChunk("NSSet *");9595Builder.AddChunk(CodeCompletionString::CK_RightParen);9596Builder.AddTextChunk("objects");9597Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,9598CXCursor_ObjCInstanceMethodDecl));9599}9600}96019602// Key-Value Observing9603// + (NSSet *)keyPathsForValuesAffectingKey9604if (!IsInstanceMethod &&9605(ReturnType.isNull() ||9606(ReturnType->isObjCObjectPointerType() &&9607ReturnType->castAs<ObjCObjectPointerType>()->getInterfaceDecl() &&9608ReturnType->castAs<ObjCObjectPointerType>()9609->getInterfaceDecl()9610->getName() == "NSSet"))) {9611std::string SelectorName =9612(Twine("keyPathsForValuesAffecting") + UpperKey).str();9613const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9614if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))9615.second) {9616if (ReturnType.isNull()) {9617Builder.AddChunk(CodeCompletionString::CK_LeftParen);9618Builder.AddTextChunk("NSSet<NSString *> *");9619Builder.AddChunk(CodeCompletionString::CK_RightParen);9620}96219622Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));9623Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,9624CXCursor_ObjCClassMethodDecl));9625}9626}96279628// + (BOOL)automaticallyNotifiesObserversForKey9629if (!IsInstanceMethod &&9630(ReturnType.isNull() || ReturnType->isIntegerType() ||9631ReturnType->isBooleanType())) {9632std::string SelectorName =9633(Twine("automaticallyNotifiesObserversOf") + UpperKey).str();9634const IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);9635if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))9636.second) {9637if (ReturnType.isNull()) {9638Builder.AddChunk(CodeCompletionString::CK_LeftParen);9639Builder.AddTextChunk("BOOL");9640Builder.AddChunk(CodeCompletionString::CK_RightParen);9641}96429643Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));9644Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,9645CXCursor_ObjCClassMethodDecl));9646}9647}9648}96499650void SemaCodeCompletion::CodeCompleteObjCMethodDecl(9651Scope *S, std::optional<bool> IsInstanceMethod, ParsedType ReturnTy) {9652ASTContext &Context = getASTContext();9653// Determine the return type of the method we're declaring, if9654// provided.9655QualType ReturnType = SemaRef.GetTypeFromParser(ReturnTy);9656Decl *IDecl = nullptr;9657if (SemaRef.CurContext->isObjCContainer()) {9658ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(SemaRef.CurContext);9659IDecl = OCD;9660}9661// Determine where we should start searching for methods.9662ObjCContainerDecl *SearchDecl = nullptr;9663bool IsInImplementation = false;9664if (Decl *D = IDecl) {9665if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {9666SearchDecl = Impl->getClassInterface();9667IsInImplementation = true;9668} else if (ObjCCategoryImplDecl *CatImpl =9669dyn_cast<ObjCCategoryImplDecl>(D)) {9670SearchDecl = CatImpl->getCategoryDecl();9671IsInImplementation = true;9672} else9673SearchDecl = dyn_cast<ObjCContainerDecl>(D);9674}96759676if (!SearchDecl && S) {9677if (DeclContext *DC = S->getEntity())9678SearchDecl = dyn_cast<ObjCContainerDecl>(DC);9679}96809681if (!SearchDecl) {9682HandleCodeCompleteResults(&SemaRef, CodeCompleter,9683CodeCompletionContext::CCC_Other, nullptr, 0);9684return;9685}96869687// Find all of the methods that we could declare/implement here.9688KnownMethodsMap KnownMethods;9689FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,9690KnownMethods);96919692// Add declarations or definitions for each of the known methods.9693typedef CodeCompletionResult Result;9694ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),9695CodeCompleter->getCodeCompletionTUInfo(),9696CodeCompletionContext::CCC_Other);9697Results.EnterNewScope();9698PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);9699for (KnownMethodsMap::iterator M = KnownMethods.begin(),9700MEnd = KnownMethods.end();9701M != MEnd; ++M) {9702ObjCMethodDecl *Method = M->second.getPointer();9703CodeCompletionBuilder Builder(Results.getAllocator(),9704Results.getCodeCompletionTUInfo());97059706// Add the '-'/'+' prefix if it wasn't provided yet.9707if (!IsInstanceMethod) {9708Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");9709Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9710}97119712// If the result type was not already provided, add it to the9713// pattern as (type).9714if (ReturnType.isNull()) {9715QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);9716AttributedType::stripOuterNullability(ResTy);9717AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,9718Policy, Builder);9719}97209721Selector Sel = Method->getSelector();97229723if (Sel.isUnarySelector()) {9724// Unary selectors have no arguments.9725Builder.AddTypedTextChunk(9726Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));9727} else {9728// Add all parameters to the pattern.9729unsigned I = 0;9730for (ObjCMethodDecl::param_iterator P = Method->param_begin(),9731PEnd = Method->param_end();9732P != PEnd; (void)++P, ++I) {9733// Add the part of the selector name.9734if (I == 0)9735Builder.AddTypedTextChunk(9736Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));9737else if (I < Sel.getNumArgs()) {9738Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9739Builder.AddTypedTextChunk(9740Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));9741} else9742break;97439744// Add the parameter type.9745QualType ParamType;9746if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)9747ParamType = (*P)->getType();9748else9749ParamType = (*P)->getOriginalType();9750ParamType = ParamType.substObjCTypeArgs(9751Context, {}, ObjCSubstitutionContext::Parameter);9752AttributedType::stripOuterNullability(ParamType);9753AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(),9754Context, Policy, Builder);97559756if (IdentifierInfo *Id = (*P)->getIdentifier())9757Builder.AddTextChunk(9758Builder.getAllocator().CopyString(Id->getName()));9759}9760}97619762if (Method->isVariadic()) {9763if (Method->param_size() > 0)9764Builder.AddChunk(CodeCompletionString::CK_Comma);9765Builder.AddTextChunk("...");9766}97679768if (IsInImplementation && Results.includeCodePatterns()) {9769// We will be defining the method here, so add a compound statement.9770Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9771Builder.AddChunk(CodeCompletionString::CK_LeftBrace);9772Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);9773if (!Method->getReturnType()->isVoidType()) {9774// If the result type is not void, add a return clause.9775Builder.AddTextChunk("return");9776Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9777Builder.AddPlaceholderChunk("expression");9778Builder.AddChunk(CodeCompletionString::CK_SemiColon);9779} else9780Builder.AddPlaceholderChunk("statements");97819782Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);9783Builder.AddChunk(CodeCompletionString::CK_RightBrace);9784}97859786unsigned Priority = CCP_CodePattern;9787auto R = Result(Builder.TakeString(), Method, Priority);9788if (!M->second.getInt())9789setInBaseClass(R);9790Results.AddResult(std::move(R));9791}97929793// Add Key-Value-Coding and Key-Value-Observing accessor methods for all of9794// the properties in this class and its categories.9795if (Context.getLangOpts().ObjC) {9796SmallVector<ObjCContainerDecl *, 4> Containers;9797Containers.push_back(SearchDecl);97989799VisitedSelectorSet KnownSelectors;9800for (KnownMethodsMap::iterator M = KnownMethods.begin(),9801MEnd = KnownMethods.end();9802M != MEnd; ++M)9803KnownSelectors.insert(M->first);98049805ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);9806if (!IFace)9807if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))9808IFace = Category->getClassInterface();98099810if (IFace)9811llvm::append_range(Containers, IFace->visible_categories());98129813if (IsInstanceMethod) {9814for (unsigned I = 0, N = Containers.size(); I != N; ++I)9815for (auto *P : Containers[I]->instance_properties())9816AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,9817KnownSelectors, Results);9818}9819}98209821Results.ExitScope();98229823HandleCodeCompleteResults(&SemaRef, CodeCompleter,9824Results.getCompletionContext(), Results.data(),9825Results.size());9826}98279828void SemaCodeCompletion::CodeCompleteObjCMethodDeclSelector(9829Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,9830ArrayRef<const IdentifierInfo *> SelIdents) {9831// If we have an external source, load the entire class method9832// pool from the AST file.9833if (SemaRef.ExternalSource) {9834for (uint32_t I = 0, N = SemaRef.ExternalSource->GetNumExternalSelectors();9835I != N; ++I) {9836Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);9837if (Sel.isNull() || SemaRef.ObjC().MethodPool.count(Sel))9838continue;98399840SemaRef.ObjC().ReadMethodPool(Sel);9841}9842}98439844// Build the set of methods we can see.9845typedef CodeCompletionResult Result;9846ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),9847CodeCompleter->getCodeCompletionTUInfo(),9848CodeCompletionContext::CCC_Other);98499850if (ReturnTy)9851Results.setPreferredType(9852SemaRef.GetTypeFromParser(ReturnTy).getNonReferenceType());98539854Results.EnterNewScope();9855for (SemaObjC::GlobalMethodPool::iterator9856M = SemaRef.ObjC().MethodPool.begin(),9857MEnd = SemaRef.ObjC().MethodPool.end();9858M != MEnd; ++M) {9859for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first9860: &M->second.second;9861MethList && MethList->getMethod(); MethList = MethList->getNext()) {9862if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))9863continue;98649865if (AtParameterName) {9866// Suggest parameter names we've seen before.9867unsigned NumSelIdents = SelIdents.size();9868if (NumSelIdents &&9869NumSelIdents <= MethList->getMethod()->param_size()) {9870ParmVarDecl *Param =9871MethList->getMethod()->parameters()[NumSelIdents - 1];9872if (Param->getIdentifier()) {9873CodeCompletionBuilder Builder(Results.getAllocator(),9874Results.getCodeCompletionTUInfo());9875Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(9876Param->getIdentifier()->getName()));9877Results.AddResult(Builder.TakeString());9878}9879}98809881continue;9882}98839884Result R(MethList->getMethod(),9885Results.getBasePriority(MethList->getMethod()), nullptr);9886R.StartParameter = SelIdents.size();9887R.AllParametersAreInformative = false;9888R.DeclaringEntity = true;9889Results.MaybeAddResult(R, SemaRef.CurContext);9890}9891}98929893Results.ExitScope();98949895if (!AtParameterName && !SelIdents.empty() &&9896SelIdents.front()->getName().starts_with("init")) {9897for (const auto &M : SemaRef.PP.macros()) {9898if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")9899continue;9900Results.EnterNewScope();9901CodeCompletionBuilder Builder(Results.getAllocator(),9902Results.getCodeCompletionTUInfo());9903Builder.AddTypedTextChunk(9904Builder.getAllocator().CopyString(M.first->getName()));9905Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,9906CXCursor_MacroDefinition));9907Results.ExitScope();9908}9909}99109911HandleCodeCompleteResults(&SemaRef, CodeCompleter,9912Results.getCompletionContext(), Results.data(),9913Results.size());9914}99159916void SemaCodeCompletion::CodeCompletePreprocessorDirective(bool InConditional) {9917ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),9918CodeCompleter->getCodeCompletionTUInfo(),9919CodeCompletionContext::CCC_PreprocessorDirective);9920Results.EnterNewScope();99219922// #if <condition>9923CodeCompletionBuilder Builder(Results.getAllocator(),9924Results.getCodeCompletionTUInfo());9925Builder.AddTypedTextChunk("if");9926Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9927Builder.AddPlaceholderChunk("condition");9928Results.AddResult(Builder.TakeString());99299930// #ifdef <macro>9931Builder.AddTypedTextChunk("ifdef");9932Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9933Builder.AddPlaceholderChunk("macro");9934Results.AddResult(Builder.TakeString());99359936// #ifndef <macro>9937Builder.AddTypedTextChunk("ifndef");9938Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9939Builder.AddPlaceholderChunk("macro");9940Results.AddResult(Builder.TakeString());99419942if (InConditional) {9943// #elif <condition>9944Builder.AddTypedTextChunk("elif");9945Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9946Builder.AddPlaceholderChunk("condition");9947Results.AddResult(Builder.TakeString());99489949// #elifdef <macro>9950Builder.AddTypedTextChunk("elifdef");9951Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9952Builder.AddPlaceholderChunk("macro");9953Results.AddResult(Builder.TakeString());99549955// #elifndef <macro>9956Builder.AddTypedTextChunk("elifndef");9957Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9958Builder.AddPlaceholderChunk("macro");9959Results.AddResult(Builder.TakeString());99609961// #else9962Builder.AddTypedTextChunk("else");9963Results.AddResult(Builder.TakeString());99649965// #endif9966Builder.AddTypedTextChunk("endif");9967Results.AddResult(Builder.TakeString());9968}99699970// #include "header"9971Builder.AddTypedTextChunk("include");9972Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9973Builder.AddTextChunk("\"");9974Builder.AddPlaceholderChunk("header");9975Builder.AddTextChunk("\"");9976Results.AddResult(Builder.TakeString());99779978// #include <header>9979Builder.AddTypedTextChunk("include");9980Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9981Builder.AddTextChunk("<");9982Builder.AddPlaceholderChunk("header");9983Builder.AddTextChunk(">");9984Results.AddResult(Builder.TakeString());99859986// #define <macro>9987Builder.AddTypedTextChunk("define");9988Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9989Builder.AddPlaceholderChunk("macro");9990Results.AddResult(Builder.TakeString());99919992// #define <macro>(<args>)9993Builder.AddTypedTextChunk("define");9994Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);9995Builder.AddPlaceholderChunk("macro");9996Builder.AddChunk(CodeCompletionString::CK_LeftParen);9997Builder.AddPlaceholderChunk("args");9998Builder.AddChunk(CodeCompletionString::CK_RightParen);9999Results.AddResult(Builder.TakeString());1000010001// #undef <macro>10002Builder.AddTypedTextChunk("undef");10003Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10004Builder.AddPlaceholderChunk("macro");10005Results.AddResult(Builder.TakeString());1000610007// #line <number>10008Builder.AddTypedTextChunk("line");10009Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10010Builder.AddPlaceholderChunk("number");10011Results.AddResult(Builder.TakeString());1001210013// #line <number> "filename"10014Builder.AddTypedTextChunk("line");10015Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10016Builder.AddPlaceholderChunk("number");10017Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10018Builder.AddTextChunk("\"");10019Builder.AddPlaceholderChunk("filename");10020Builder.AddTextChunk("\"");10021Results.AddResult(Builder.TakeString());1002210023// #error <message>10024Builder.AddTypedTextChunk("error");10025Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10026Builder.AddPlaceholderChunk("message");10027Results.AddResult(Builder.TakeString());1002810029// #pragma <arguments>10030Builder.AddTypedTextChunk("pragma");10031Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10032Builder.AddPlaceholderChunk("arguments");10033Results.AddResult(Builder.TakeString());1003410035if (getLangOpts().ObjC) {10036// #import "header"10037Builder.AddTypedTextChunk("import");10038Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10039Builder.AddTextChunk("\"");10040Builder.AddPlaceholderChunk("header");10041Builder.AddTextChunk("\"");10042Results.AddResult(Builder.TakeString());1004310044// #import <header>10045Builder.AddTypedTextChunk("import");10046Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10047Builder.AddTextChunk("<");10048Builder.AddPlaceholderChunk("header");10049Builder.AddTextChunk(">");10050Results.AddResult(Builder.TakeString());10051}1005210053// #include_next "header"10054Builder.AddTypedTextChunk("include_next");10055Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10056Builder.AddTextChunk("\"");10057Builder.AddPlaceholderChunk("header");10058Builder.AddTextChunk("\"");10059Results.AddResult(Builder.TakeString());1006010061// #include_next <header>10062Builder.AddTypedTextChunk("include_next");10063Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10064Builder.AddTextChunk("<");10065Builder.AddPlaceholderChunk("header");10066Builder.AddTextChunk(">");10067Results.AddResult(Builder.TakeString());1006810069// #warning <message>10070Builder.AddTypedTextChunk("warning");10071Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10072Builder.AddPlaceholderChunk("message");10073Results.AddResult(Builder.TakeString());1007410075// Note: #ident and #sccs are such crazy anachronisms that we don't provide10076// completions for them. And __include_macros is a Clang-internal extension10077// that we don't want to encourage anyone to use.1007810079// FIXME: we don't support #assert or #unassert, so don't suggest them.10080Results.ExitScope();1008110082HandleCodeCompleteResults(&SemaRef, CodeCompleter,10083Results.getCompletionContext(), Results.data(),10084Results.size());10085}1008610087void SemaCodeCompletion::CodeCompleteInPreprocessorConditionalExclusion(10088Scope *S) {10089CodeCompleteOrdinaryName(S, S->getFnParent()10090? SemaCodeCompletion::PCC_RecoveryInFunction10091: SemaCodeCompletion::PCC_Namespace);10092}1009310094void SemaCodeCompletion::CodeCompletePreprocessorMacroName(bool IsDefinition) {10095ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),10096CodeCompleter->getCodeCompletionTUInfo(),10097IsDefinition ? CodeCompletionContext::CCC_MacroName10098: CodeCompletionContext::CCC_MacroNameUse);10099if (!IsDefinition && CodeCompleter->includeMacros()) {10100// Add just the names of macros, not their arguments.10101CodeCompletionBuilder Builder(Results.getAllocator(),10102Results.getCodeCompletionTUInfo());10103Results.EnterNewScope();10104for (Preprocessor::macro_iterator M = SemaRef.PP.macro_begin(),10105MEnd = SemaRef.PP.macro_end();10106M != MEnd; ++M) {10107Builder.AddTypedTextChunk(10108Builder.getAllocator().CopyString(M->first->getName()));10109Results.AddResult(CodeCompletionResult(10110Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));10111}10112Results.ExitScope();10113} else if (IsDefinition) {10114// FIXME: Can we detect when the user just wrote an include guard above?10115}1011610117HandleCodeCompleteResults(&SemaRef, CodeCompleter,10118Results.getCompletionContext(), Results.data(),10119Results.size());10120}1012110122void SemaCodeCompletion::CodeCompletePreprocessorExpression() {10123ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),10124CodeCompleter->getCodeCompletionTUInfo(),10125CodeCompletionContext::CCC_PreprocessorExpression);1012610127if (CodeCompleter->includeMacros())10128AddMacroResults(SemaRef.PP, Results, CodeCompleter->loadExternal(), true);1012910130// defined (<macro>)10131Results.EnterNewScope();10132CodeCompletionBuilder Builder(Results.getAllocator(),10133Results.getCodeCompletionTUInfo());10134Builder.AddTypedTextChunk("defined");10135Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);10136Builder.AddChunk(CodeCompletionString::CK_LeftParen);10137Builder.AddPlaceholderChunk("macro");10138Builder.AddChunk(CodeCompletionString::CK_RightParen);10139Results.AddResult(Builder.TakeString());10140Results.ExitScope();1014110142HandleCodeCompleteResults(&SemaRef, CodeCompleter,10143Results.getCompletionContext(), Results.data(),10144Results.size());10145}1014610147void SemaCodeCompletion::CodeCompletePreprocessorMacroArgument(10148Scope *S, IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned Argument) {10149// FIXME: In the future, we could provide "overload" results, much like we10150// do for function calls.1015110152// Now just ignore this. There will be another code-completion callback10153// for the expanded tokens.10154}1015510156// This handles completion inside an #include filename, e.g. #include <foo/ba10157// We look for the directory "foo" under each directory on the include path,10158// list its files, and reassemble the appropriate #include.10159void SemaCodeCompletion::CodeCompleteIncludedFile(llvm::StringRef Dir,10160bool Angled) {10161// RelDir should use /, but unescaped \ is possible on windows!10162// Our completions will normalize to / for simplicity, this case is rare.10163std::string RelDir = llvm::sys::path::convert_to_slash(Dir);10164// We need the native slashes for the actual file system interactions.10165SmallString<128> NativeRelDir = StringRef(RelDir);10166llvm::sys::path::native(NativeRelDir);10167llvm::vfs::FileSystem &FS =10168SemaRef.getSourceManager().getFileManager().getVirtualFileSystem();1016910170ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),10171CodeCompleter->getCodeCompletionTUInfo(),10172CodeCompletionContext::CCC_IncludedFile);10173llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.1017410175// Helper: adds one file or directory completion result.10176auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {10177SmallString<64> TypedChunk = Filename;10178// Directory completion is up to the slash, e.g. <sys/10179TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');10180auto R = SeenResults.insert(TypedChunk);10181if (R.second) { // New completion10182const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);10183*R.first = InternedTyped; // Avoid dangling StringRef.10184CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),10185CodeCompleter->getCodeCompletionTUInfo());10186Builder.AddTypedTextChunk(InternedTyped);10187// The result is a "Pattern", which is pretty opaque.10188// We may want to include the real filename to allow smart ranking.10189Results.AddResult(CodeCompletionResult(Builder.TakeString()));10190}10191};1019210193// Helper: scans IncludeDir for nice files, and adds results for each.10194auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,10195bool IsSystem,10196DirectoryLookup::LookupType_t LookupType) {10197llvm::SmallString<128> Dir = IncludeDir;10198if (!NativeRelDir.empty()) {10199if (LookupType == DirectoryLookup::LT_Framework) {10200// For a framework dir, #include <Foo/Bar/> actually maps to10201// a path of Foo.framework/Headers/Bar/.10202auto Begin = llvm::sys::path::begin(NativeRelDir);10203auto End = llvm::sys::path::end(NativeRelDir);1020410205llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");10206llvm::sys::path::append(Dir, ++Begin, End);10207} else {10208llvm::sys::path::append(Dir, NativeRelDir);10209}10210}1021110212const StringRef &Dirname = llvm::sys::path::filename(Dir);10213const bool isQt = Dirname.starts_with("Qt") || Dirname == "ActiveQt";10214const bool ExtensionlessHeaders =10215IsSystem || isQt || Dir.ends_with(".framework/Headers");10216std::error_code EC;10217unsigned Count = 0;10218for (auto It = FS.dir_begin(Dir, EC);10219!EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {10220if (++Count == 2500) // If we happen to hit a huge directory,10221break; // bail out early so we're not too slow.10222StringRef Filename = llvm::sys::path::filename(It->path());1022310224// To know whether a symlink should be treated as file or a directory, we10225// have to stat it. This should be cheap enough as there shouldn't be many10226// symlinks.10227llvm::sys::fs::file_type Type = It->type();10228if (Type == llvm::sys::fs::file_type::symlink_file) {10229if (auto FileStatus = FS.status(It->path()))10230Type = FileStatus->getType();10231}10232switch (Type) {10233case llvm::sys::fs::file_type::directory_file:10234// All entries in a framework directory must have a ".framework" suffix,10235// but the suffix does not appear in the source code's include/import.10236if (LookupType == DirectoryLookup::LT_Framework &&10237NativeRelDir.empty() && !Filename.consume_back(".framework"))10238break;1023910240AddCompletion(Filename, /*IsDirectory=*/true);10241break;10242case llvm::sys::fs::file_type::regular_file: {10243// Only files that really look like headers. (Except in special dirs).10244const bool IsHeader = Filename.ends_with_insensitive(".h") ||10245Filename.ends_with_insensitive(".hh") ||10246Filename.ends_with_insensitive(".hpp") ||10247Filename.ends_with_insensitive(".hxx") ||10248Filename.ends_with_insensitive(".inc") ||10249(ExtensionlessHeaders && !Filename.contains('.'));10250if (!IsHeader)10251break;10252AddCompletion(Filename, /*IsDirectory=*/false);10253break;10254}10255default:10256break;10257}10258}10259};1026010261// Helper: adds results relative to IncludeDir, if possible.10262auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,10263bool IsSystem) {10264switch (IncludeDir.getLookupType()) {10265case DirectoryLookup::LT_HeaderMap:10266// header maps are not (currently) enumerable.10267break;10268case DirectoryLookup::LT_NormalDir:10269AddFilesFromIncludeDir(IncludeDir.getDirRef()->getName(), IsSystem,10270DirectoryLookup::LT_NormalDir);10271break;10272case DirectoryLookup::LT_Framework:10273AddFilesFromIncludeDir(IncludeDir.getFrameworkDirRef()->getName(),10274IsSystem, DirectoryLookup::LT_Framework);10275break;10276}10277};1027810279// Finally with all our helpers, we can scan the include path.10280// Do this in standard order so deduplication keeps the right file.10281// (In case we decide to add more details to the results later).10282const auto &S = SemaRef.PP.getHeaderSearchInfo();10283using llvm::make_range;10284if (!Angled) {10285// The current directory is on the include path for "quoted" includes.10286if (auto CurFile = SemaRef.PP.getCurrentFileLexer()->getFileEntry())10287AddFilesFromIncludeDir(CurFile->getDir().getName(), false,10288DirectoryLookup::LT_NormalDir);10289for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))10290AddFilesFromDirLookup(D, false);10291}10292for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))10293AddFilesFromDirLookup(D, false);10294for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))10295AddFilesFromDirLookup(D, true);1029610297HandleCodeCompleteResults(&SemaRef, CodeCompleter,10298Results.getCompletionContext(), Results.data(),10299Results.size());10300}1030110302void SemaCodeCompletion::CodeCompleteNaturalLanguage() {10303HandleCodeCompleteResults(&SemaRef, CodeCompleter,10304CodeCompletionContext::CCC_NaturalLanguage, nullptr,103050);10306}1030710308void SemaCodeCompletion::CodeCompleteAvailabilityPlatformName() {10309ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),10310CodeCompleter->getCodeCompletionTUInfo(),10311CodeCompletionContext::CCC_Other);10312Results.EnterNewScope();10313static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};10314for (const char *Platform : llvm::ArrayRef(Platforms)) {10315Results.AddResult(CodeCompletionResult(Platform));10316Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(10317Twine(Platform) + "ApplicationExtension")));10318}10319Results.ExitScope();10320HandleCodeCompleteResults(&SemaRef, CodeCompleter,10321Results.getCompletionContext(), Results.data(),10322Results.size());10323}1032410325void SemaCodeCompletion::GatherGlobalCodeCompletions(10326CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,10327SmallVectorImpl<CodeCompletionResult> &Results) {10328ResultBuilder Builder(SemaRef, Allocator, CCTUInfo,10329CodeCompletionContext::CCC_Recovery);10330if (!CodeCompleter || CodeCompleter->includeGlobals()) {10331CodeCompletionDeclConsumer Consumer(10332Builder, getASTContext().getTranslationUnitDecl());10333SemaRef.LookupVisibleDecls(getASTContext().getTranslationUnitDecl(),10334Sema::LookupAnyName, Consumer,10335!CodeCompleter || CodeCompleter->loadExternal());10336}1033710338if (!CodeCompleter || CodeCompleter->includeMacros())10339AddMacroResults(SemaRef.PP, Builder,10340!CodeCompleter || CodeCompleter->loadExternal(), true);1034110342Results.clear();10343Results.insert(Results.end(), Builder.data(),10344Builder.data() + Builder.size());10345}1034610347SemaCodeCompletion::SemaCodeCompletion(Sema &S,10348CodeCompleteConsumer *CompletionConsumer)10349: SemaBase(S), CodeCompleter(CompletionConsumer) {}103501035110352