blob: 487ba46c20b6d936368e10f1449d0429bbd1ae26 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Douglas Gregor2436e712009-09-17 21:32:03 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the code-completion semantic actions.
10//
11//===----------------------------------------------------------------------===//
Eric Liub91e0812018-10-02 10:29:00 +000012#include "clang/AST/Decl.h"
Ilya Biryukov98397552018-12-05 17:38:39 +000013#include "clang/AST/DeclBase.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000014#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000015#include "clang/AST/DeclObjC.h"
Kadir Cetinkaya42e94782020-01-23 13:28:16 +010016#include "clang/AST/DeclTemplate.h"
17#include "clang/AST/Expr.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000018#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000019#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000020#include "clang/AST/QualTypeNames.h"
Sam McCall3dea5272019-06-10 15:17:52 +000021#include "clang/AST/Type.h"
Jordan Rose4938f272013-02-09 10:09:43 +000022#include "clang/Basic/CharInfo.h"
Sam McCall3dea5272019-06-10 15:17:52 +000023#include "clang/Basic/Specifiers.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000024#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000025#include "clang/Lex/MacroInfo.h"
26#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000027#include "clang/Sema/CodeCompleteConsumer.h"
Kadir Cetinkaya42e94782020-01-23 13:28:16 +010028#include "clang/Sema/Designator.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000029#include "clang/Sema/Lookup.h"
30#include "clang/Sema/Overload.h"
31#include "clang/Sema/Scope.h"
32#include "clang/Sema/ScopeInfo.h"
Kadir Cetinkaya42e94782020-01-23 13:28:16 +010033#include "clang/Sema/Sema.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000034#include "clang/Sema/SemaInternal.h"
Kadir Cetinkaya42e94782020-01-23 13:28:16 +010035#include "llvm/ADT/ArrayRef.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000036#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000037#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000038#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000039#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000040#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000041#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000042#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000043#include "llvm/ADT/iterator_range.h"
Kadir Cetinkaya42e94782020-01-23 13:28:16 +010044#include "llvm/Support/Casting.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000045#include "llvm/Support/Path.h"
Kadir Cetinkaya1f946ee2020-01-13 09:00:19 +010046#include "llvm/Support/raw_ostream.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000047#include <list>
48#include <map>
Ilya Biryukovcabab292019-05-24 10:18:39 +000049#include <string>
Douglas Gregor3545ff42009-09-21 16:56:56 +000050#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000051
52using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000053using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000054
Douglas Gregor3545ff42009-09-21 16:56:56 +000055namespace {
Fangrui Song050229d2018-11-24 00:14:31 +000056/// A container of code-completion results.
57class ResultBuilder {
58public:
59 /// The type of a name-lookup filter, which can be provided to the
60 /// name-lookup routines to specify which declarations should be included in
61 /// the result set (when it returns true) and which declarations should be
62 /// filtered out (returns false).
63 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000064
Fangrui Song050229d2018-11-24 00:14:31 +000065 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000066
Fangrui Song050229d2018-11-24 00:14:31 +000067private:
68 /// The actual results we have found.
69 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000070
Fangrui Song050229d2018-11-24 00:14:31 +000071 /// A record of all of the declarations we have found and placed
72 /// into the result set, used to ensure that no declaration ever gets into
73 /// the result set twice.
74 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000075
Fangrui Song050229d2018-11-24 00:14:31 +000076 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000077
Fangrui Song050229d2018-11-24 00:14:31 +000078 /// An entry in the shadow map, which is optimized to store
79 /// a single (declaration, index) mapping (the common case) but
80 /// can also store a list of (declaration, index) mappings.
81 class ShadowMapEntry {
82 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000083
Fangrui Song050229d2018-11-24 00:14:31 +000084 /// Contains either the solitary NamedDecl * or a vector
85 /// of (declaration, index) pairs.
86 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000087
Fangrui Song050229d2018-11-24 00:14:31 +000088 /// When the entry contains a single declaration, this is
89 /// the index associated with that entry.
90 unsigned SingleDeclIndex;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000091
Douglas Gregor3545ff42009-09-21 16:56:56 +000092 public:
Fangrui Song050229d2018-11-24 00:14:31 +000093 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
Sam McCall3dea5272019-06-10 15:17:52 +000094 ShadowMapEntry(const ShadowMapEntry &) = delete;
95 ShadowMapEntry(ShadowMapEntry &&Move) { *this = std::move(Move); }
96 ShadowMapEntry &operator=(const ShadowMapEntry &) = delete;
97 ShadowMapEntry &operator=(ShadowMapEntry &&Move) {
98 SingleDeclIndex = Move.SingleDeclIndex;
99 DeclOrVector = Move.DeclOrVector;
100 Move.DeclOrVector = nullptr;
101 return *this;
102 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000103
Fangrui Song050229d2018-11-24 00:14:31 +0000104 void Add(const NamedDecl *ND, unsigned Index) {
105 if (DeclOrVector.isNull()) {
106 // 0 - > 1 elements: just set the single element information.
107 DeclOrVector = ND;
108 SingleDeclIndex = Index;
109 return;
110 }
111
112 if (const NamedDecl *PrevND =
113 DeclOrVector.dyn_cast<const NamedDecl *>()) {
114 // 1 -> 2 elements: create the vector of results and push in the
115 // existing declaration.
116 DeclIndexPairVector *Vec = new DeclIndexPairVector;
117 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
118 DeclOrVector = Vec;
119 }
120
121 // Add the new element to the end of the vector.
122 DeclOrVector.get<DeclIndexPairVector *>()->push_back(
123 DeclIndexPair(ND, Index));
124 }
125
Sam McCall3dea5272019-06-10 15:17:52 +0000126 ~ShadowMapEntry() {
Fangrui Song050229d2018-11-24 00:14:31 +0000127 if (DeclIndexPairVector *Vec =
128 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
129 delete Vec;
130 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05fcf842010-11-02 20:36:02 +0000131 }
132 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000133
Fangrui Song050229d2018-11-24 00:14:31 +0000134 // Iteration.
135 class iterator;
136 iterator begin() const;
137 iterator end() const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000138 };
Fangrui Song050229d2018-11-24 00:14:31 +0000139
140 /// A mapping from declaration names to the declarations that have
141 /// this name within a particular scope and their index within the list of
142 /// results.
143 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
144
145 /// The semantic analysis object for which results are being
146 /// produced.
147 Sema &SemaRef;
148
149 /// The allocator used to allocate new code-completion strings.
150 CodeCompletionAllocator &Allocator;
151
152 CodeCompletionTUInfo &CCTUInfo;
153
154 /// If non-NULL, a filter function used to remove any code-completion
155 /// results that are not desirable.
156 LookupFilter Filter;
157
158 /// Whether we should allow declarations as
159 /// nested-name-specifiers that would otherwise be filtered out.
160 bool AllowNestedNameSpecifiers;
161
162 /// If set, the type that we would prefer our resulting value
163 /// declarations to have.
164 ///
165 /// Closely matching the preferred type gives a boost to a result's
166 /// priority.
167 CanQualType PreferredType;
168
169 /// A list of shadow maps, which is used to model name hiding at
170 /// different levels of, e.g., the inheritance hierarchy.
171 std::list<ShadowMap> ShadowMaps;
172
Sam McCall3dea5272019-06-10 15:17:52 +0000173 /// Overloaded C++ member functions found by SemaLookup.
174 /// Used to determine when one overload is dominated by another.
175 llvm::DenseMap<std::pair<DeclContext *, /*Name*/uintptr_t>, ShadowMapEntry>
176 OverloadMap;
177
Fangrui Song050229d2018-11-24 00:14:31 +0000178 /// If we're potentially referring to a C++ member function, the set
179 /// of qualifiers applied to the object type.
180 Qualifiers ObjectTypeQualifiers;
Sam McCall3dea5272019-06-10 15:17:52 +0000181 /// The kind of the object expression, for rvalue/lvalue overloads.
182 ExprValueKind ObjectKind;
Fangrui Song050229d2018-11-24 00:14:31 +0000183
184 /// Whether the \p ObjectTypeQualifiers field is active.
185 bool HasObjectTypeQualifiers;
186
187 /// The selector that we prefer.
188 Selector PreferredSelector;
189
190 /// The completion context in which we are gathering results.
191 CodeCompletionContext CompletionContext;
192
193 /// If we are in an instance method definition, the \@implementation
194 /// object.
195 ObjCImplementationDecl *ObjCImplementation;
196
197 void AdjustResultPriorityForDecl(Result &R);
198
199 void MaybeAddConstructorResults(Result R);
200
201public:
202 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
203 CodeCompletionTUInfo &CCTUInfo,
204 const CodeCompletionContext &CompletionContext,
205 LookupFilter Filter = nullptr)
206 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
207 Filter(Filter), AllowNestedNameSpecifiers(false),
208 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
209 ObjCImplementation(nullptr) {
210 // If this is an Objective-C instance method definition, dig out the
211 // corresponding implementation.
212 switch (CompletionContext.getKind()) {
213 case CodeCompletionContext::CCC_Expression:
214 case CodeCompletionContext::CCC_ObjCMessageReceiver:
215 case CodeCompletionContext::CCC_ParenthesizedExpression:
216 case CodeCompletionContext::CCC_Statement:
217 case CodeCompletionContext::CCC_Recovery:
218 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
219 if (Method->isInstanceMethod())
220 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
221 ObjCImplementation = Interface->getImplementation();
222 break;
223
224 default:
225 break;
226 }
227 }
228
229 /// Determine the priority for a reference to the given declaration.
230 unsigned getBasePriority(const NamedDecl *D);
231
232 /// Whether we should include code patterns in the completion
233 /// results.
234 bool includeCodePatterns() const {
235 return SemaRef.CodeCompleter &&
236 SemaRef.CodeCompleter->includeCodePatterns();
237 }
238
239 /// Set the filter used for code-completion results.
240 void setFilter(LookupFilter Filter) { this->Filter = Filter; }
241
242 Result *data() { return Results.empty() ? nullptr : &Results.front(); }
243 unsigned size() const { return Results.size(); }
244 bool empty() const { return Results.empty(); }
245
246 /// Specify the preferred type.
247 void setPreferredType(QualType T) {
248 PreferredType = SemaRef.Context.getCanonicalType(T);
249 }
250
251 /// Set the cv-qualifiers on the object type, for us in filtering
252 /// calls to member functions.
253 ///
254 /// When there are qualifiers in this set, they will be used to filter
255 /// out member functions that aren't available (because there will be a
256 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
257 /// match.
Sam McCall3dea5272019-06-10 15:17:52 +0000258 void setObjectTypeQualifiers(Qualifiers Quals, ExprValueKind Kind) {
Fangrui Song050229d2018-11-24 00:14:31 +0000259 ObjectTypeQualifiers = Quals;
Sam McCall3dea5272019-06-10 15:17:52 +0000260 ObjectKind = Kind;
Fangrui Song050229d2018-11-24 00:14:31 +0000261 HasObjectTypeQualifiers = true;
262 }
263
264 /// Set the preferred selector.
265 ///
266 /// When an Objective-C method declaration result is added, and that
267 /// method's selector matches this preferred selector, we give that method
268 /// a slight priority boost.
269 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
270
271 /// Retrieve the code-completion context for which results are
272 /// being collected.
273 const CodeCompletionContext &getCompletionContext() const {
274 return CompletionContext;
275 }
276
277 /// Specify whether nested-name-specifiers are allowed.
278 void allowNestedNameSpecifiers(bool Allow = true) {
279 AllowNestedNameSpecifiers = Allow;
280 }
281
282 /// Return the semantic analysis object for which we are collecting
283 /// code completion results.
284 Sema &getSema() const { return SemaRef; }
285
286 /// Retrieve the allocator used to allocate code completion strings.
287 CodeCompletionAllocator &getAllocator() const { return Allocator; }
288
289 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
290
291 /// Determine whether the given declaration is at all interesting
292 /// as a code-completion result.
293 ///
294 /// \param ND the declaration that we are inspecting.
295 ///
296 /// \param AsNestedNameSpecifier will be set true if this declaration is
297 /// only interesting when it is a nested-name-specifier.
298 bool isInterestingDecl(const NamedDecl *ND,
299 bool &AsNestedNameSpecifier) const;
300
301 /// Check whether the result is hidden by the Hiding declaration.
302 ///
303 /// \returns true if the result is hidden and cannot be found, false if
304 /// the hidden result could still be found. When false, \p R may be
305 /// modified to describe how the result can be found (e.g., via extra
306 /// qualification).
307 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
308 const NamedDecl *Hiding);
309
310 /// Add a new result to this result set (if it isn't already in one
311 /// of the shadow maps), or replace an existing result (for, e.g., a
312 /// redeclaration).
313 ///
314 /// \param R the result to add (if it is unique).
315 ///
316 /// \param CurContext the context in which this result will be named.
317 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
318
319 /// Add a new result to this result set, where we already know
320 /// the hiding declaration (if any).
321 ///
322 /// \param R the result to add (if it is unique).
323 ///
324 /// \param CurContext the context in which this result will be named.
325 ///
326 /// \param Hiding the declaration that hides the result.
327 ///
328 /// \param InBaseClass whether the result was found in a base
329 /// class of the searched context.
330 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
331 bool InBaseClass);
332
333 /// Add a new non-declaration result to this result set.
334 void AddResult(Result R);
335
336 /// Enter into a new scope.
337 void EnterNewScope();
338
339 /// Exit from the current scope.
340 void ExitScope();
341
342 /// Ignore this declaration, if it is seen again.
343 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
344
345 /// Add a visited context.
346 void addVisitedContext(DeclContext *Ctx) {
347 CompletionContext.addVisitedContext(Ctx);
348 }
349
350 /// \name Name lookup predicates
351 ///
352 /// These predicates can be passed to the name lookup functions to filter the
353 /// results of name lookup. All of the predicates have the same type, so that
354 ///
355 //@{
356 bool IsOrdinaryName(const NamedDecl *ND) const;
357 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
358 bool IsIntegralConstantValue(const NamedDecl *ND) const;
359 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
360 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
361 bool IsEnum(const NamedDecl *ND) const;
362 bool IsClassOrStruct(const NamedDecl *ND) const;
363 bool IsUnion(const NamedDecl *ND) const;
364 bool IsNamespace(const NamedDecl *ND) const;
365 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
366 bool IsType(const NamedDecl *ND) const;
367 bool IsMember(const NamedDecl *ND) const;
368 bool IsObjCIvar(const NamedDecl *ND) const;
369 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
370 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
371 bool IsObjCCollection(const NamedDecl *ND) const;
372 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
373 //@}
374};
375} // namespace
Douglas Gregor3545ff42009-09-21 16:56:56 +0000376
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000377void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
378 if (isa<BlockDecl>(S.CurContext)) {
379 if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000380 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000381 Type = BSI->ReturnType;
382 ExpectedLoc = Tok;
383 }
384 } else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000385 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000386 Type = Function->getReturnType();
387 ExpectedLoc = Tok;
388 } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000389 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000390 Type = Method->getReturnType();
391 ExpectedLoc = Tok;
392 }
393}
394
395void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {
396 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000397 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000398 Type = VD ? VD->getType() : QualType();
399 ExpectedLoc = Tok;
400}
401
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000402void PreferredTypeBuilder::enterFunctionArgument(
403 SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) {
404 this->ComputeType = ComputeType;
405 Type = QualType();
406 ExpectedLoc = Tok;
407}
408
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000409void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,
410 SourceLocation LParLoc) {
411 // expected type for parenthesized expression does not change.
412 if (ExpectedLoc == LParLoc)
413 ExpectedLoc = Tok;
414}
415
416static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
417 tok::TokenKind Op) {
418 if (!LHS)
419 return QualType();
420
421 QualType LHSType = LHS->getType();
422 if (LHSType->isPointerType()) {
423 if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
424 return S.getASTContext().getPointerDiffType();
425 // Pointer difference is more common than subtracting an int from a pointer.
426 if (Op == tok::minus)
427 return LHSType;
428 }
429
430 switch (Op) {
431 // No way to infer the type of RHS from LHS.
432 case tok::comma:
433 return QualType();
434 // Prefer the type of the left operand for all of these.
435 // Arithmetic operations.
436 case tok::plus:
437 case tok::plusequal:
438 case tok::minus:
439 case tok::minusequal:
440 case tok::percent:
441 case tok::percentequal:
442 case tok::slash:
443 case tok::slashequal:
444 case tok::star:
445 case tok::starequal:
446 // Assignment.
447 case tok::equal:
448 // Comparison operators.
449 case tok::equalequal:
450 case tok::exclaimequal:
451 case tok::less:
452 case tok::lessequal:
453 case tok::greater:
454 case tok::greaterequal:
455 case tok::spaceship:
456 return LHS->getType();
457 // Binary shifts are often overloaded, so don't try to guess those.
458 case tok::greatergreater:
459 case tok::greatergreaterequal:
460 case tok::lessless:
461 case tok::lesslessequal:
462 if (LHSType->isIntegralOrEnumerationType())
463 return S.getASTContext().IntTy;
464 return QualType();
465 // Logical operators, assume we want bool.
466 case tok::ampamp:
467 case tok::pipepipe:
468 case tok::caretcaret:
469 return S.getASTContext().BoolTy;
470 // Operators often used for bit manipulation are typically used with the type
471 // of the left argument.
472 case tok::pipe:
473 case tok::pipeequal:
474 case tok::caret:
475 case tok::caretequal:
476 case tok::amp:
477 case tok::ampequal:
478 if (LHSType->isIntegralOrEnumerationType())
479 return LHSType;
480 return QualType();
481 // RHS should be a pointer to a member of the 'LHS' type, but we can't give
482 // any particular type here.
483 case tok::periodstar:
484 case tok::arrowstar:
485 return QualType();
486 default:
487 // FIXME(ibiryukov): handle the missing op, re-add the assertion.
488 // assert(false && "unhandled binary op");
489 return QualType();
490 }
491}
492
493/// Get preferred type for an argument of an unary expression. \p ContextType is
494/// preferred type of the whole unary expression.
495static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType,
496 tok::TokenKind Op) {
497 switch (Op) {
498 case tok::exclaim:
499 return S.getASTContext().BoolTy;
500 case tok::amp:
501 if (!ContextType.isNull() && ContextType->isPointerType())
502 return ContextType->getPointeeType();
503 return QualType();
504 case tok::star:
505 if (ContextType.isNull())
506 return QualType();
507 return S.getASTContext().getPointerType(ContextType.getNonReferenceType());
508 case tok::plus:
509 case tok::minus:
510 case tok::tilde:
511 case tok::minusminus:
512 case tok::plusplus:
513 if (ContextType.isNull())
514 return S.getASTContext().IntTy;
515 // leave as is, these operators typically return the same type.
516 return ContextType;
517 case tok::kw___real:
518 case tok::kw___imag:
519 return QualType();
520 default:
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000521 assert(false && "unhandled unary op");
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000522 return QualType();
523 }
524}
525
526void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,
527 tok::TokenKind Op) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000528 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000529 Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);
530 ExpectedLoc = Tok;
531}
532
533void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok,
534 Expr *Base) {
535 if (!Base)
536 return;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000537 // Do we have expected type for Base?
538 if (ExpectedLoc != Base->getBeginLoc())
539 return;
540 // Keep the expected type, only update the location.
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000541 ExpectedLoc = Tok;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000542 return;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000543}
544
545void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,
546 tok::TokenKind OpKind,
547 SourceLocation OpLoc) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000548 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000549 Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);
550 ExpectedLoc = Tok;
551}
552
553void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,
554 Expr *LHS) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000555 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000556 Type = S.getASTContext().IntTy;
557 ExpectedLoc = Tok;
558}
559
560void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,
561 QualType CastType) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000562 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000563 Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();
564 ExpectedLoc = Tok;
565}
566
567void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000568 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000569 Type = S.getASTContext().BoolTy;
570 ExpectedLoc = Tok;
571}
572
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000573class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000574 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000575 unsigned SingleDeclIndex;
576
577public:
578 typedef DeclIndexPair value_type;
579 typedef value_type reference;
580 typedef std::ptrdiff_t difference_type;
581 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000582
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000583 class pointer {
584 DeclIndexPair Value;
585
586 public:
Fangrui Song050229d2018-11-24 00:14:31 +0000587 pointer(const DeclIndexPair &Value) : Value(Value) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000588
Fangrui Song050229d2018-11-24 00:14:31 +0000589 const DeclIndexPair *operator->() const { return &Value; }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000590 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000591
592 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000593
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000594 iterator(const NamedDecl *SingleDecl, unsigned Index)
Fangrui Song050229d2018-11-24 00:14:31 +0000595 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000596
597 iterator(const DeclIndexPair *Iterator)
Fangrui Song050229d2018-11-24 00:14:31 +0000598 : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000599
600 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000601 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000602 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000603 SingleDeclIndex = 0;
604 return *this;
605 }
606
Fangrui Song050229d2018-11-24 00:14:31 +0000607 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000608 ++I;
609 DeclOrIterator = I;
610 return *this;
611 }
612
Chris Lattner9795b392010-09-04 18:12:20 +0000613 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000614 iterator tmp(*this);
615 ++(*this);
616 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000617 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000618
619 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000620 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000621 return reference(ND, SingleDeclIndex);
622
Fangrui Song050229d2018-11-24 00:14:31 +0000623 return *DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000624 }
625
Fangrui Song050229d2018-11-24 00:14:31 +0000626 pointer operator->() const { return pointer(**this); }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000627
628 friend bool operator==(const iterator &X, const iterator &Y) {
Fangrui Song050229d2018-11-24 00:14:31 +0000629 return X.DeclOrIterator.getOpaqueValue() ==
630 Y.DeclOrIterator.getOpaqueValue() &&
631 X.SingleDeclIndex == Y.SingleDeclIndex;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000632 }
633
634 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000635 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000636 }
637};
638
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000639ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000640ResultBuilder::ShadowMapEntry::begin() const {
641 if (DeclOrVector.isNull())
642 return iterator();
643
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000644 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000645 return iterator(ND, SingleDeclIndex);
646
647 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
648}
649
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000650ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000651ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000652 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000653 return iterator();
654
655 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
656}
657
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000658/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000659/// (\p CurContext) to the target context (\p TargetContext).
660///
661/// \param Context the AST context in which the qualification will be used.
662///
663/// \param CurContext the context where an entity is being named, which is
664/// typically based on the current scope.
665///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000666/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000667/// resides.
668///
669/// \returns a nested name specifier that refers into the target context, or
670/// NULL if no qualification is needed.
671static NestedNameSpecifier *
Fangrui Song050229d2018-11-24 00:14:31 +0000672getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000673 const DeclContext *TargetContext) {
674 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000675
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000676 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000677 CommonAncestor && !CommonAncestor->Encloses(CurContext);
678 CommonAncestor = CommonAncestor->getLookupParent()) {
679 if (CommonAncestor->isTransparentContext() ||
680 CommonAncestor->isFunctionOrMethod())
681 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000682
Douglas Gregor2af2f672009-09-21 20:12:40 +0000683 TargetParents.push_back(CommonAncestor);
684 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000685
686 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000687 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000688 const DeclContext *Parent = TargetParents.pop_back_val();
689
Fangrui Song050229d2018-11-24 00:14:31 +0000690 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000691 if (!Namespace->getIdentifier())
692 continue;
693
Douglas Gregor2af2f672009-09-21 20:12:40 +0000694 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Fangrui Song050229d2018-11-24 00:14:31 +0000695 } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
696 Result = NestedNameSpecifier::Create(
697 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000698 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000699 return Result;
700}
701
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000702// Some declarations have reserved names that we don't want to ever show.
703// Filter out names reserved for the implementation if they come from a
704// system header.
705static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
706 const IdentifierInfo *Id = ND->getIdentifier();
707 if (!Id)
708 return false;
709
710 // Ignore reserved names for compiler provided decls.
Vedant Kumar568db782019-11-13 18:19:32 -0800711 if (Id->isReservedName() && ND->getLocation().isInvalid())
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000712 return true;
713
714 // For system headers ignore only double-underscore names.
715 // This allows for system headers providing private symbols with a single
716 // underscore.
Vedant Kumar568db782019-11-13 18:19:32 -0800717 if (Id->isReservedName(/*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000718 SemaRef.SourceMgr.isInSystemHeader(
719 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
720 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000721
722 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000723}
724
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000725bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000726 bool &AsNestedNameSpecifier) const {
727 AsNestedNameSpecifier = false;
728
Richard Smithf2005d32015-12-29 23:34:32 +0000729 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000730 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000731
732 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000733 if (!ND->getDeclName())
734 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000735
Douglas Gregor3545ff42009-09-21 16:56:56 +0000736 // Friend declarations and declarations introduced due to friends are never
737 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000738 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000739 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000740
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000741 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000742 if (isa<ClassTemplateSpecializationDecl>(ND) ||
743 isa<ClassTemplatePartialSpecializationDecl>(ND))
744 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000745
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000746 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000747 if (isa<UsingDecl>(ND))
748 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000749
750 if (shouldIgnoreDueToReservedName(ND, SemaRef))
751 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000752
Douglas Gregor59cab552010-08-16 23:05:20 +0000753 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000754 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
755 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000756 AsNestedNameSpecifier = true;
757
Douglas Gregor3545ff42009-09-21 16:56:56 +0000758 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000759 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000760 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000761 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000762 IsNestedNameSpecifier(ND) &&
763 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000764 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000765 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
766 AsNestedNameSpecifier = true;
767 return true;
768 }
769
Douglas Gregor7c208612010-01-14 00:20:49 +0000770 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000771 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000772 // ... then it must be interesting!
773 return true;
774}
775
Douglas Gregore0717ab2010-01-14 00:41:07 +0000776bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000777 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000778 // In C, there is no way to refer to a hidden name.
779 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
780 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000781 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000782 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000783
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000784 const DeclContext *HiddenCtx =
785 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000786
Douglas Gregore0717ab2010-01-14 00:41:07 +0000787 // There is no way to qualify a name declared in a function or method.
788 if (HiddenCtx->isFunctionOrMethod())
789 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000790
Sebastian Redl50c68252010-08-31 00:36:30 +0000791 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000792 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000793
Douglas Gregore0717ab2010-01-14 00:41:07 +0000794 // We can refer to the result with the appropriate qualification. Do it.
795 R.Hidden = true;
796 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000797
Douglas Gregore0717ab2010-01-14 00:41:07 +0000798 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000799 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000800 R.Declaration->getDeclContext());
801 return false;
802}
803
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000804/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000805/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000806SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000807 switch (T->getTypeClass()) {
808 case Type::Builtin:
809 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000810 case BuiltinType::Void:
811 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000812
Fangrui Song050229d2018-11-24 00:14:31 +0000813 case BuiltinType::NullPtr:
814 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000815
Fangrui Song050229d2018-11-24 00:14:31 +0000816 case BuiltinType::Overload:
817 case BuiltinType::Dependent:
818 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000819
Fangrui Song050229d2018-11-24 00:14:31 +0000820 case BuiltinType::ObjCId:
821 case BuiltinType::ObjCClass:
822 case BuiltinType::ObjCSel:
823 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000824
Fangrui Song050229d2018-11-24 00:14:31 +0000825 default:
826 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000827 }
David Blaikie8a40f702012-01-17 06:56:22 +0000828
Douglas Gregor95887f92010-07-08 23:20:03 +0000829 case Type::Complex:
830 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000831
Douglas Gregor95887f92010-07-08 23:20:03 +0000832 case Type::Pointer:
833 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000834
Douglas Gregor95887f92010-07-08 23:20:03 +0000835 case Type::BlockPointer:
836 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000837
Douglas Gregor95887f92010-07-08 23:20:03 +0000838 case Type::LValueReference:
839 case Type::RValueReference:
840 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000841
Douglas Gregor95887f92010-07-08 23:20:03 +0000842 case Type::ConstantArray:
843 case Type::IncompleteArray:
844 case Type::VariableArray:
845 case Type::DependentSizedArray:
846 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000847
Douglas Gregor95887f92010-07-08 23:20:03 +0000848 case Type::DependentSizedExtVector:
849 case Type::Vector:
850 case Type::ExtVector:
851 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000852
Douglas Gregor95887f92010-07-08 23:20:03 +0000853 case Type::FunctionProto:
854 case Type::FunctionNoProto:
855 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000856
Douglas Gregor95887f92010-07-08 23:20:03 +0000857 case Type::Record:
858 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000859
Douglas Gregor95887f92010-07-08 23:20:03 +0000860 case Type::Enum:
861 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000862
Douglas Gregor95887f92010-07-08 23:20:03 +0000863 case Type::ObjCObject:
864 case Type::ObjCInterface:
865 case Type::ObjCObjectPointer:
866 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000867
Douglas Gregor95887f92010-07-08 23:20:03 +0000868 default:
869 return STC_Other;
870 }
871}
872
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000873/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000874/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000875QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000876 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000877
Fangrui Song050229d2018-11-24 00:14:31 +0000878 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000879 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000880 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000881 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000882
Douglas Gregor95887f92010-07-08 23:20:03 +0000883 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000884 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000885 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000886 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000887 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000888 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000889 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000890 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000891 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000892 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000893 T = Value->getType();
Ilya Biryukovc514ade2019-01-24 10:41:43 +0000894
895 if (T.isNull())
Douglas Gregor95887f92010-07-08 23:20:03 +0000896 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000897
898 // Dig through references, function pointers, and block pointers to
899 // get down to the likely type of an expression when the entity is
900 // used.
901 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000902 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000903 T = Ref->getPointeeType();
904 continue;
905 }
906
Fangrui Song050229d2018-11-24 00:14:31 +0000907 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000908 if (Pointer->getPointeeType()->isFunctionType()) {
909 T = Pointer->getPointeeType();
910 continue;
911 }
912
913 break;
914 }
915
Fangrui Song050229d2018-11-24 00:14:31 +0000916 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000917 T = Block->getPointeeType();
918 continue;
919 }
920
Fangrui Song050229d2018-11-24 00:14:31 +0000921 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000922 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000923 continue;
924 }
925
926 break;
927 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000928
Douglas Gregoraf670a82011-04-14 20:33:34 +0000929 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000930}
931
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000932unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
933 if (!ND)
934 return CCP_Unlikely;
935
936 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000937 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
938 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000939 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000940 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000941 if (ImplicitParam->getIdentifier() &&
942 ImplicitParam->getIdentifier()->isStr("_cmd"))
943 return CCP_ObjC_cmd;
944
945 return CCP_LocalDeclaration;
946 }
Richard Smith541b38b2013-09-20 01:15:31 +0000947
948 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000949 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
950 // Explicit destructor calls are very rare.
951 if (isa<CXXDestructorDecl>(ND))
952 return CCP_Unlikely;
953 // Explicit operator and conversion function calls are also very rare.
954 auto DeclNameKind = ND->getDeclName().getNameKind();
955 if (DeclNameKind == DeclarationName::CXXOperatorName ||
956 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
957 DeclNameKind == DeclarationName::CXXConversionFunctionName)
958 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000959 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000960 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000961
962 // Content-based decisions.
963 if (isa<EnumConstantDecl>(ND))
964 return CCP_Constant;
965
Douglas Gregor52e0de42013-01-31 05:03:46 +0000966 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
967 // message receiver, or parenthesized expression context. There, it's as
968 // likely that the user will want to write a type as other declarations.
969 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
970 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000971 CompletionContext.getKind() ==
972 CodeCompletionContext::CCC_ObjCMessageReceiver ||
973 CompletionContext.getKind() ==
974 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000975 return CCP_Type;
976
977 return CCP_Declaration;
978}
979
Douglas Gregor50832e02010-09-20 22:39:41 +0000980void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
981 // If this is an Objective-C method declaration whose selector matches our
982 // preferred selector, give it a priority boost.
983 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000984 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000985 if (PreferredSelector == Method->getSelector())
986 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000987
Douglas Gregor50832e02010-09-20 22:39:41 +0000988 // If we have a preferred type, adjust the priority for results with exactly-
989 // matching or nearly-matching types.
990 if (!PreferredType.isNull()) {
991 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
992 if (!T.isNull()) {
993 CanQualType TC = SemaRef.Context.getCanonicalType(T);
994 // Check for exactly-matching types (modulo qualifiers).
995 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
996 R.Priority /= CCF_ExactTypeMatch;
997 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +0000998 else if ((getSimplifiedTypeClass(PreferredType) ==
999 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +00001000 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001001 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +00001002 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001003 }
Douglas Gregor95887f92010-07-08 23:20:03 +00001004}
1005
Benjamin Kramer756ecb82019-02-11 14:52:15 +00001006static DeclContext::lookup_result getConstructors(ASTContext &Context,
1007 const CXXRecordDecl *Record) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001008 QualType RecordTy = Context.getTypeDeclType(Record);
1009 DeclarationName ConstructorName =
1010 Context.DeclarationNames.getCXXConstructorName(
1011 Context.getCanonicalType(RecordTy));
1012 return Record->lookup(ConstructorName);
1013}
1014
Douglas Gregor0212fd72010-09-21 16:06:22 +00001015void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001016 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +00001017 !CompletionContext.wantConstructorResults())
1018 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001019
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001020 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +00001021 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001022 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001023 Record = ClassTemplate->getTemplatedDecl();
1024 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
1025 // Skip specializations and partial specializations.
1026 if (isa<ClassTemplateSpecializationDecl>(Record))
1027 return;
1028 } else {
1029 // There are no constructors here.
1030 return;
1031 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001032
Douglas Gregor0212fd72010-09-21 16:06:22 +00001033 Record = Record->getDefinition();
1034 if (!Record)
1035 return;
1036
Fangrui Song050229d2018-11-24 00:14:31 +00001037 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001038 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001039 R.CursorKind = getCursorKindForDecl(R.Declaration);
1040 Results.push_back(R);
1041 }
1042}
1043
Sam McCall63c59722018-01-22 20:44:47 +00001044static bool isConstructor(const Decl *ND) {
1045 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
1046 ND = Tmpl->getTemplatedDecl();
1047 return isa<CXXConstructorDecl>(ND);
1048}
1049
Douglas Gregor7c208612010-01-14 00:20:49 +00001050void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
1051 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001052
Douglas Gregor7c208612010-01-14 00:20:49 +00001053 if (R.Kind != Result::RK_Declaration) {
1054 // For non-declaration results, just add the result.
1055 Results.push_back(R);
1056 return;
1057 }
1058
1059 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001060 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
1061 CodeCompletionResult Result(Using->getTargetDecl(),
1062 getBasePriority(Using->getTargetDecl()),
1063 R.Qualifier);
1064 Result.ShadowDecl = Using;
1065 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +00001066 return;
1067 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001068
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001069 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +00001070 unsigned IDNS = CanonDecl->getIdentifierNamespace();
1071
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001072 bool AsNestedNameSpecifier = false;
1073 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +00001074 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001075
Douglas Gregor0212fd72010-09-21 16:06:22 +00001076 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001077 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001078 return;
1079
Douglas Gregor3545ff42009-09-21 16:56:56 +00001080 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001081 ShadowMapEntry::iterator I, IEnd;
1082 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
1083 if (NamePos != SMap.end()) {
1084 I = NamePos->second.begin();
1085 IEnd = NamePos->second.end();
1086 }
1087
1088 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001089 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001090 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001091 if (ND->getCanonicalDecl() == CanonDecl) {
1092 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001093 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001094
Douglas Gregor3545ff42009-09-21 16:56:56 +00001095 // We're done.
1096 return;
1097 }
1098 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001099
Douglas Gregor3545ff42009-09-21 16:56:56 +00001100 // This is a new declaration in this scope. However, check whether this
1101 // declaration name is hidden by a similarly-named declaration in an outer
1102 // scope.
1103 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
1104 --SMEnd;
1105 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001106 ShadowMapEntry::iterator I, IEnd;
1107 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
1108 if (NamePos != SM->end()) {
1109 I = NamePos->second.begin();
1110 IEnd = NamePos->second.end();
1111 }
1112 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001113 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +00001114 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +00001115 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
1116 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001117 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001118
Douglas Gregor3545ff42009-09-21 16:56:56 +00001119 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +00001120 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
1121 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001122 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001123 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001124
Douglas Gregor3545ff42009-09-21 16:56:56 +00001125 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +00001126 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001127 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001128
Douglas Gregor3545ff42009-09-21 16:56:56 +00001129 break;
1130 }
1131 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001132
Douglas Gregor3545ff42009-09-21 16:56:56 +00001133 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001134 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001135 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00001136
Douglas Gregore412a5a2009-09-23 22:26:46 +00001137 // If the filter is for nested-name-specifiers, then this result starts a
1138 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001139 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +00001140 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001141 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001142 } else
Fangrui Song050229d2018-11-24 00:14:31 +00001143 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001144
Douglas Gregor5bf52692009-09-22 23:15:58 +00001145 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +00001146 if (R.QualifierIsInformative && !R.Qualifier &&
1147 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001148 const DeclContext *Ctx = R.Declaration->getDeclContext();
1149 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001150 R.Qualifier =
1151 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001152 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001153 R.Qualifier = NestedNameSpecifier::Create(
1154 SemaRef.Context, nullptr, false,
1155 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +00001156 else
1157 R.QualifierIsInformative = false;
1158 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001159
Douglas Gregor3545ff42009-09-21 16:56:56 +00001160 // Insert this result into the set of results and into the current shadow
1161 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001162 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001163 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001164
Douglas Gregor0212fd72010-09-21 16:06:22 +00001165 if (!AsNestedNameSpecifier)
1166 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001167}
1168
Eric Liu4a7cd632018-10-24 12:57:27 +00001169static void setInBaseClass(ResultBuilder::Result &R) {
1170 R.Priority += CCD_InBaseClass;
1171 R.InBaseClass = true;
1172}
1173
Sam McCall3dea5272019-06-10 15:17:52 +00001174enum class OverloadCompare { BothViable, Dominates, Dominated };
1175// Will Candidate ever be called on the object, when overloaded with Incumbent?
1176// Returns Dominates if Candidate is always called, Dominated if Incumbent is
1177// always called, BothViable if either may be called dependending on arguments.
1178// Precondition: must actually be overloads!
1179static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate,
1180 const CXXMethodDecl &Incumbent,
1181 const Qualifiers &ObjectQuals,
1182 ExprValueKind ObjectKind) {
Ilya Biryukov8613e902019-10-04 08:10:27 +00001183 // Base/derived shadowing is handled elsewhere.
1184 if (Candidate.getDeclContext() != Incumbent.getDeclContext())
1185 return OverloadCompare::BothViable;
Sam McCall3dea5272019-06-10 15:17:52 +00001186 if (Candidate.isVariadic() != Incumbent.isVariadic() ||
1187 Candidate.getNumParams() != Incumbent.getNumParams() ||
1188 Candidate.getMinRequiredArguments() !=
1189 Incumbent.getMinRequiredArguments())
1190 return OverloadCompare::BothViable;
1191 for (unsigned I = 0, E = Candidate.getNumParams(); I != E; ++I)
1192 if (Candidate.parameters()[I]->getType().getCanonicalType() !=
1193 Incumbent.parameters()[I]->getType().getCanonicalType())
1194 return OverloadCompare::BothViable;
1195 if (!llvm::empty(Candidate.specific_attrs<EnableIfAttr>()) ||
1196 !llvm::empty(Incumbent.specific_attrs<EnableIfAttr>()))
1197 return OverloadCompare::BothViable;
1198 // At this point, we know calls can't pick one or the other based on
1199 // arguments, so one of the two must win. (Or both fail, handled elsewhere).
1200 RefQualifierKind CandidateRef = Candidate.getRefQualifier();
1201 RefQualifierKind IncumbentRef = Incumbent.getRefQualifier();
1202 if (CandidateRef != IncumbentRef) {
1203 // If the object kind is LValue/RValue, there's one acceptable ref-qualifier
1204 // and it can't be mixed with ref-unqualified overloads (in valid code).
1205
1206 // For xvalue objects, we prefer the rvalue overload even if we have to
1207 // add qualifiers (which is rare, because const&& is rare).
1208 if (ObjectKind == clang::VK_XValue)
1209 return CandidateRef == RQ_RValue ? OverloadCompare::Dominates
1210 : OverloadCompare::Dominated;
1211 }
1212 // Now the ref qualifiers are the same (or we're in some invalid state).
1213 // So make some decision based on the qualifiers.
1214 Qualifiers CandidateQual = Candidate.getMethodQualifiers();
1215 Qualifiers IncumbentQual = Incumbent.getMethodQualifiers();
1216 bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual);
1217 bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual);
1218 if (CandidateSuperset == IncumbentSuperset)
1219 return OverloadCompare::BothViable;
1220 return IncumbentSuperset ? OverloadCompare::Dominates
1221 : OverloadCompare::Dominated;
1222}
1223
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001224void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +00001225 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001226 if (R.Kind != Result::RK_Declaration) {
1227 // For non-declaration results, just add the result.
1228 Results.push_back(R);
1229 return;
1230 }
1231
Douglas Gregorc580c522010-01-14 01:09:38 +00001232 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +00001233 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001234 CodeCompletionResult Result(Using->getTargetDecl(),
1235 getBasePriority(Using->getTargetDecl()),
1236 R.Qualifier);
1237 Result.ShadowDecl = Using;
1238 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +00001239 return;
1240 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001241
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001242 bool AsNestedNameSpecifier = false;
1243 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +00001244 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001245
Douglas Gregor0212fd72010-09-21 16:06:22 +00001246 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001247 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001248 return;
1249
Douglas Gregorc580c522010-01-14 01:09:38 +00001250 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1251 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001252
Douglas Gregorc580c522010-01-14 01:09:38 +00001253 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001254 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001255 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001256
Douglas Gregorc580c522010-01-14 01:09:38 +00001257 // If the filter is for nested-name-specifiers, then this result starts a
1258 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001259 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001260 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001261 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001262 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1263 InBaseClass &&
1264 isa<CXXRecordDecl>(
1265 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001266 R.QualifierIsInformative = true;
1267
Douglas Gregorc580c522010-01-14 01:09:38 +00001268 // If this result is supposed to have an informative qualifier, add one.
1269 if (R.QualifierIsInformative && !R.Qualifier &&
1270 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001271 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001272 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1273 R.Qualifier =
1274 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1275 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1276 R.Qualifier = NestedNameSpecifier::Create(
1277 SemaRef.Context, nullptr, false,
1278 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001279 else
1280 R.QualifierIsInformative = false;
1281 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001282
Douglas Gregora2db7932010-05-26 22:00:08 +00001283 // Adjust the priority if this result comes from a base class.
1284 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001285 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001286
Douglas Gregor50832e02010-09-20 22:39:41 +00001287 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001288
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001289 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001290 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001291 if (Method->isInstance()) {
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00001292 Qualifiers MethodQuals = Method->getMethodQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001293 if (ObjectTypeQualifiers == MethodQuals)
1294 R.Priority += CCD_ObjectQualifierMatch;
1295 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001296 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001297 // qualifiers.
1298 return;
1299 }
Sam McCall3dea5272019-06-10 15:17:52 +00001300 // Detect cases where a ref-qualified method cannot be invoked.
1301 switch (Method->getRefQualifier()) {
1302 case RQ_LValue:
1303 if (ObjectKind != VK_LValue && !MethodQuals.hasConst())
1304 return;
1305 break;
1306 case RQ_RValue:
1307 if (ObjectKind == VK_LValue)
1308 return;
1309 break;
1310 case RQ_None:
1311 break;
1312 }
1313
1314 /// Check whether this dominates another overloaded method, which should
1315 /// be suppressed (or vice versa).
1316 /// Motivating case is const_iterator begin() const vs iterator begin().
1317 auto &OverloadSet = OverloadMap[std::make_pair(
1318 CurContext, Method->getDeclName().getAsOpaqueInteger())];
Mark de Wever3ec61282019-12-17 21:54:32 +01001319 for (const DeclIndexPair Entry : OverloadSet) {
Sam McCall3dea5272019-06-10 15:17:52 +00001320 Result &Incumbent = Results[Entry.second];
1321 switch (compareOverloads(*Method,
1322 *cast<CXXMethodDecl>(Incumbent.Declaration),
1323 ObjectTypeQualifiers, ObjectKind)) {
1324 case OverloadCompare::Dominates:
1325 // Replace the dominated overload with this one.
1326 // FIXME: if the overload dominates multiple incumbents then we
1327 // should remove all. But two overloads is by far the common case.
1328 Incumbent = std::move(R);
1329 return;
1330 case OverloadCompare::Dominated:
1331 // This overload can't be called, drop it.
1332 return;
1333 case OverloadCompare::BothViable:
1334 break;
1335 }
1336 }
1337 OverloadSet.Add(Method, Results.size());
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001338 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001339
Douglas Gregorc580c522010-01-14 01:09:38 +00001340 // Insert this result into the set of results.
1341 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001342
Douglas Gregor0212fd72010-09-21 16:06:22 +00001343 if (!AsNestedNameSpecifier)
1344 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001345}
1346
Douglas Gregor78a21012010-01-14 16:01:26 +00001347void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001348 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001349 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001350 Results.push_back(R);
1351}
1352
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001353/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001354void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001355
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001356/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001357void ResultBuilder::ExitScope() {
1358 ShadowMaps.pop_back();
1359}
1360
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001361/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001362/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001363bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001364 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001365
Richard Smith541b38b2013-09-20 01:15:31 +00001366 // If name lookup finds a local extern declaration, then we are in a
1367 // context where it behaves like an ordinary name.
1368 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001369 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001370 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001371 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001372 if (isa<ObjCIvarDecl>(ND))
1373 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001374 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001375
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001376 return ND->getIdentifierNamespace() & IDNS;
1377}
1378
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001379/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001380/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001381bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001382 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001383 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001384 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001385 // Objective-C interfaces names are not filtered by this method because they
1386 // can be used in a class property expression. We can still filter out
1387 // @class declarations though.
1388 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1389 if (!ID->getDefinition())
1390 return false;
1391 }
1392
Richard Smith541b38b2013-09-20 01:15:31 +00001393 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001394 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001395 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001396 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001397 if (isa<ObjCIvarDecl>(ND))
1398 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001399 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001400
Douglas Gregor70febae2010-05-28 00:49:12 +00001401 return ND->getIdentifierNamespace() & IDNS;
1402}
1403
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001404bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001405 if (!IsOrdinaryNonTypeName(ND))
1406 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001407
Fangrui Song050229d2018-11-24 00:14:31 +00001408 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001409 if (VD->getType()->isIntegralOrEnumerationType())
1410 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001411
Douglas Gregor85b50632010-07-28 21:50:18 +00001412 return false;
1413}
1414
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001415/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001416/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001417bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001418 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001419
Richard Smith541b38b2013-09-20 01:15:31 +00001420 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001421 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001422 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001423
Fangrui Song050229d2018-11-24 00:14:31 +00001424 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1425 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001426}
1427
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001428/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001429/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001430bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001431 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001432 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001433 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001434
Douglas Gregor3545ff42009-09-21 16:56:56 +00001435 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1436}
1437
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001438/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001439bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001440 return isa<EnumDecl>(ND);
1441}
1442
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001443/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001444bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001445 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001446 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001447 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001448
1449 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001450 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1451 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1452 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001453
Douglas Gregor3545ff42009-09-21 16:56:56 +00001454 return false;
1455}
1456
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001457/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001458bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001459 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001460 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001461 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001462
Fangrui Song050229d2018-11-24 00:14:31 +00001463 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001464 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001465
Douglas Gregor3545ff42009-09-21 16:56:56 +00001466 return false;
1467}
1468
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001469/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001470bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001471 return isa<NamespaceDecl>(ND);
1472}
1473
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001474/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001475/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001476bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001477 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001478}
1479
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001480/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001481bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001482 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001483 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001484}
1485
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001486/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001487/// "." or "->". Only value declarations, nested name specifiers, and
1488/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001489bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001490 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001491 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001492 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001493}
1494
Douglas Gregora817a192010-05-27 23:06:34 +00001495static bool isObjCReceiverType(ASTContext &C, QualType T) {
1496 T = C.getCanonicalType(T);
1497 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001498 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001499 case Type::ObjCInterface:
1500 case Type::ObjCObjectPointer:
1501 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001502
Douglas Gregora817a192010-05-27 23:06:34 +00001503 case Type::Builtin:
1504 switch (cast<BuiltinType>(T)->getKind()) {
1505 case BuiltinType::ObjCId:
1506 case BuiltinType::ObjCClass:
1507 case BuiltinType::ObjCSel:
1508 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001509
Douglas Gregora817a192010-05-27 23:06:34 +00001510 default:
1511 break;
1512 }
1513 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001514
Douglas Gregora817a192010-05-27 23:06:34 +00001515 default:
1516 break;
1517 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001518
David Blaikiebbafb8a2012-03-11 07:00:24 +00001519 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001520 return false;
1521
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001522 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001523 // particular class type has any conversions to Objective-C types. For now,
1524 // just accept all class types.
1525 return T->isDependentType() || T->isRecordType();
1526}
1527
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001528bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001529 QualType T = getDeclUsageType(SemaRef.Context, ND);
1530 if (T.isNull())
1531 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001532
Douglas Gregora817a192010-05-27 23:06:34 +00001533 T = SemaRef.Context.getBaseElementType(T);
1534 return isObjCReceiverType(SemaRef.Context, T);
1535}
1536
Fangrui Song050229d2018-11-24 00:14:31 +00001537bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1538 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001539 if (IsObjCMessageReceiver(ND))
1540 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001541
Fangrui Song050229d2018-11-24 00:14:31 +00001542 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001543 if (!Var)
1544 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001545
Douglas Gregord8c61782012-02-15 15:34:24 +00001546 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1547}
1548
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001549bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001550 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1551 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001552 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001553
Douglas Gregor68762e72010-08-23 21:17:50 +00001554 QualType T = getDeclUsageType(SemaRef.Context, ND);
1555 if (T.isNull())
1556 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001557
Douglas Gregor68762e72010-08-23 21:17:50 +00001558 T = SemaRef.Context.getBaseElementType(T);
1559 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001560 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001561 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001562}
Douglas Gregora817a192010-05-27 23:06:34 +00001563
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001564bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001565 return false;
1566}
1567
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001568/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001569/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001570bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001571 return isa<ObjCIvarDecl>(ND);
1572}
1573
Douglas Gregorc580c522010-01-14 01:09:38 +00001574namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001575
Fangrui Song050229d2018-11-24 00:14:31 +00001576/// Visible declaration consumer that adds a code-completion result
1577/// for each visible declaration.
1578class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1579 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001580 DeclContext *InitialLookupCtx;
1581 // NamingClass and BaseType are used for access-checking. See
1582 // Sema::IsSimplyAccessible for details.
1583 CXXRecordDecl *NamingClass;
1584 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001585 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001586
Fangrui Song050229d2018-11-24 00:14:31 +00001587public:
1588 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001589 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1590 QualType BaseType = QualType(),
1591 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1592 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1593 FixIts(std::move(FixIts)) {
1594 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1595 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1596 if (BaseType.isNull()) {
1597 auto ThisType = Results.getSema().getCurrentThisType();
1598 if (!ThisType.isNull()) {
1599 assert(ThisType->isPointerType());
1600 BaseType = ThisType->getPointeeType();
1601 if (!NamingClass)
1602 NamingClass = BaseType->getAsCXXRecordDecl();
1603 }
1604 }
1605 this->BaseType = BaseType;
1606 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001607
Fangrui Song050229d2018-11-24 00:14:31 +00001608 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1609 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001610 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001611 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001612 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001613 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001614
Fangrui Song050229d2018-11-24 00:14:31 +00001615 void EnteredContext(DeclContext *Ctx) override {
1616 Results.addVisitedContext(Ctx);
1617 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001618
1619private:
1620 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1621 // Naming class to use for access check. In most cases it was provided
1622 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1623 // for unqualified lookup we fallback to the \p Ctx in which we found the
1624 // member.
1625 auto *NamingClass = this->NamingClass;
1626 QualType BaseType = this->BaseType;
1627 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1628 if (!NamingClass)
1629 NamingClass = Cls;
1630 // When we emulate implicit 'this->' in an unqualified lookup, we might
1631 // end up with an invalid naming class. In that case, we avoid emulating
1632 // 'this->' qualifier to satisfy preconditions of the access checking.
1633 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1634 !NamingClass->isDerivedFrom(Cls)) {
1635 NamingClass = Cls;
1636 BaseType = QualType();
1637 }
1638 } else {
1639 // The decl was found outside the C++ class, so only ObjC access checks
1640 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1641 // out.
1642 NamingClass = nullptr;
1643 BaseType = QualType();
1644 }
1645 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1646 }
Fangrui Song050229d2018-11-24 00:14:31 +00001647};
1648} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001649
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001650/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001651static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001652 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001653 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001654 Results.AddResult(Result("short", CCP_Type));
1655 Results.AddResult(Result("long", CCP_Type));
1656 Results.AddResult(Result("signed", CCP_Type));
1657 Results.AddResult(Result("unsigned", CCP_Type));
1658 Results.AddResult(Result("void", CCP_Type));
1659 Results.AddResult(Result("char", CCP_Type));
1660 Results.AddResult(Result("int", CCP_Type));
1661 Results.AddResult(Result("float", CCP_Type));
1662 Results.AddResult(Result("double", CCP_Type));
1663 Results.AddResult(Result("enum", CCP_Type));
1664 Results.AddResult(Result("struct", CCP_Type));
1665 Results.AddResult(Result("union", CCP_Type));
1666 Results.AddResult(Result("const", CCP_Type));
1667 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001668
Douglas Gregor3545ff42009-09-21 16:56:56 +00001669 if (LangOpts.C99) {
1670 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001671 Results.AddResult(Result("_Complex", CCP_Type));
1672 Results.AddResult(Result("_Imaginary", CCP_Type));
1673 Results.AddResult(Result("_Bool", CCP_Type));
1674 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001675 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001676
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001677 CodeCompletionBuilder Builder(Results.getAllocator(),
1678 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001679 if (LangOpts.CPlusPlus) {
1680 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001681 Results.AddResult(
1682 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001683 Results.AddResult(Result("class", CCP_Type));
1684 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001685
Douglas Gregorf4c33342010-05-28 00:22:41 +00001686 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001687 Builder.AddTypedTextChunk("typename");
1688 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1689 Builder.AddPlaceholderChunk("qualifier");
1690 Builder.AddTextChunk("::");
1691 Builder.AddPlaceholderChunk("name");
1692 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001693
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001694 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001695 Results.AddResult(Result("auto", CCP_Type));
1696 Results.AddResult(Result("char16_t", CCP_Type));
1697 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001698
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001699 Builder.AddTypedTextChunk("decltype");
1700 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1701 Builder.AddPlaceholderChunk("expression");
1702 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1703 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001704 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001705 } else
1706 Results.AddResult(Result("__auto_type", CCP_Type));
1707
Richard Smith7b301e22018-05-24 21:51:52 +00001708 // GNU keywords
1709 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001710 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001711 // Results.AddResult(Result("_Decimal32"));
1712 // Results.AddResult(Result("_Decimal64"));
1713 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001714
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("typeof");
1716 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1717 Builder.AddPlaceholderChunk("expression");
1718 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001719
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001720 Builder.AddTypedTextChunk("typeof");
1721 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1722 Builder.AddPlaceholderChunk("type");
1723 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1724 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001725 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001726
1727 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001728 Results.AddResult(Result("_Nonnull", CCP_Type));
1729 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1730 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001731}
1732
John McCallfaf5fb42010-08-26 23:41:50 +00001733static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001734 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001735 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001736 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001737 // Note: we don't suggest either "auto" or "register", because both
1738 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1739 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001740 Results.AddResult(Result("extern"));
1741 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001742
1743 if (LangOpts.CPlusPlus11) {
1744 CodeCompletionAllocator &Allocator = Results.getAllocator();
1745 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1746
1747 // alignas
1748 Builder.AddTypedTextChunk("alignas");
1749 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1750 Builder.AddPlaceholderChunk("expression");
1751 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1752 Results.AddResult(Result(Builder.TakeString()));
1753
1754 Results.AddResult(Result("constexpr"));
1755 Results.AddResult(Result("thread_local"));
1756 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001757}
1758
John McCallfaf5fb42010-08-26 23:41:50 +00001759static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001760 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001761 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001762 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001763 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001764 case Sema::PCC_Class:
1765 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001766 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001767 Results.AddResult(Result("explicit"));
1768 Results.AddResult(Result("friend"));
1769 Results.AddResult(Result("mutable"));
1770 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001771 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001772 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001773
John McCallfaf5fb42010-08-26 23:41:50 +00001774 case Sema::PCC_ObjCInterface:
1775 case Sema::PCC_ObjCImplementation:
1776 case Sema::PCC_Namespace:
1777 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001778 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001779 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001780 break;
1781
John McCallfaf5fb42010-08-26 23:41:50 +00001782 case Sema::PCC_ObjCInstanceVariableList:
1783 case Sema::PCC_Expression:
1784 case Sema::PCC_Statement:
1785 case Sema::PCC_ForInit:
1786 case Sema::PCC_Condition:
1787 case Sema::PCC_RecoveryInFunction:
1788 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001789 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001790 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001791 break;
1792 }
1793}
1794
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001795static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1796static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1797static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001798 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001799static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001800 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001801static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001802 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001803static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001804
Douglas Gregorf4c33342010-05-28 00:22:41 +00001805static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001806 CodeCompletionBuilder Builder(Results.getAllocator(),
1807 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001808 Builder.AddTypedTextChunk("typedef");
1809 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1810 Builder.AddPlaceholderChunk("type");
1811 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1812 Builder.AddPlaceholderChunk("name");
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001813 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001814 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001815}
1816
John McCallfaf5fb42010-08-26 23:41:50 +00001817static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001818 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001819 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001820 case Sema::PCC_Namespace:
1821 case Sema::PCC_Class:
1822 case Sema::PCC_ObjCInstanceVariableList:
1823 case Sema::PCC_Template:
1824 case Sema::PCC_MemberTemplate:
1825 case Sema::PCC_Statement:
1826 case Sema::PCC_RecoveryInFunction:
1827 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001828 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001829 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001830 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001831
John McCallfaf5fb42010-08-26 23:41:50 +00001832 case Sema::PCC_Expression:
1833 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001834 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001835
Douglas Gregor5e35d592010-09-14 23:59:36 +00001836 case Sema::PCC_ObjCInterface:
1837 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001838 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001839
John McCallfaf5fb42010-08-26 23:41:50 +00001840 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001841 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001842 }
David Blaikie8a40f702012-01-17 06:56:22 +00001843
1844 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001845}
1846
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001847static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1848 const Preprocessor &PP) {
1849 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001850 Policy.AnonymousTagLocations = false;
1851 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001852 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001853 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001854 return Policy;
1855}
1856
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001857/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001858static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1859 return getCompletionPrintingPolicy(S.Context, S.PP);
1860}
1861
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001862/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001863/// that has the appropriate lifetime for code completion.
1864///
1865/// This routine provides a fast path where we provide constant strings for
1866/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001867static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001868 const PrintingPolicy &Policy,
1869 CodeCompletionAllocator &Allocator) {
1870 if (!T.getLocalQualifiers()) {
1871 // Built-in type names are constant strings.
1872 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001873 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001874
Douglas Gregore5c79d52011-10-18 21:20:17 +00001875 // Anonymous tag types are constant strings.
1876 if (const TagType *TagT = dyn_cast<TagType>(T))
1877 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001878 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001879 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001880 case TTK_Struct:
1881 return "struct <anonymous>";
1882 case TTK_Interface:
1883 return "__interface <anonymous>";
1884 case TTK_Class:
1885 return "class <anonymous>";
1886 case TTK_Union:
1887 return "union <anonymous>";
1888 case TTK_Enum:
1889 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001890 }
1891 }
1892 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001893
Douglas Gregore5c79d52011-10-18 21:20:17 +00001894 // Slow path: format the type as a string.
1895 std::string Result;
1896 T.getAsStringInternal(Result, Policy);
1897 return Allocator.CopyString(Result);
1898}
1899
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001900/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001901static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1902 QualType ThisTy = S.getCurrentThisType();
1903 if (ThisTy.isNull())
1904 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001905
Douglas Gregord8c61782012-02-15 15:34:24 +00001906 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001907 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001908 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001909 Builder.AddResultTypeChunk(
1910 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001911 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001912 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001913}
1914
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001915static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1916 ResultBuilder &Results,
1917 const LangOptions &LangOpts) {
1918 if (!LangOpts.CPlusPlus11)
1919 return;
1920
1921 Builder.AddTypedTextChunk("static_assert");
1922 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1923 Builder.AddPlaceholderChunk("expression");
1924 Builder.AddChunk(CodeCompletionString::CK_Comma);
1925 Builder.AddPlaceholderChunk("message");
1926 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001927 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001928 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1929}
1930
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001931static void AddOverrideResults(ResultBuilder &Results,
1932 const CodeCompletionContext &CCContext,
1933 CodeCompletionBuilder &Builder) {
1934 Sema &S = Results.getSema();
1935 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1936 // If not inside a class/struct/union return empty.
1937 if (!CR)
1938 return;
1939 // First store overrides within current class.
1940 // These are stored by name to make querying fast in the later step.
1941 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1942 for (auto *Method : CR->methods()) {
1943 if (!Method->isVirtual() || !Method->getIdentifier())
1944 continue;
1945 Overrides[Method->getName()].push_back(Method);
1946 }
1947
1948 for (const auto &Base : CR->bases()) {
1949 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1950 if (!BR)
1951 continue;
1952 for (auto *Method : BR->methods()) {
1953 if (!Method->isVirtual() || !Method->getIdentifier())
1954 continue;
1955 const auto it = Overrides.find(Method->getName());
1956 bool IsOverriden = false;
1957 if (it != Overrides.end()) {
1958 for (auto *MD : it->second) {
1959 // If the method in current body is not an overload of this virtual
1960 // function, then it overrides this one.
1961 if (!S.IsOverload(MD, Method, false)) {
1962 IsOverriden = true;
1963 break;
1964 }
1965 }
1966 }
1967 if (!IsOverriden) {
1968 // Generates a new CodeCompletionResult by taking this function and
1969 // converting it into an override declaration with only one chunk in the
1970 // final CodeCompletionString as a TypedTextChunk.
1971 std::string OverrideSignature;
1972 llvm::raw_string_ostream OS(OverrideSignature);
1973 CodeCompletionResult CCR(Method, 0);
1974 PrintingPolicy Policy =
1975 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1976 auto *CCS = CCR.createCodeCompletionStringForOverride(
1977 S.getPreprocessor(), S.getASTContext(), Builder,
1978 /*IncludeBriefComments=*/false, CCContext, Policy);
1979 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1980 }
1981 }
1982 }
1983}
1984
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001985/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001986static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1987 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001988 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001989 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001990
John McCall276321a2010-08-25 06:19:51 +00001991 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001992 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001993 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001994 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001995 if (Results.includeCodePatterns()) {
1996 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001997 Builder.AddTypedTextChunk("namespace");
1998 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1999 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002000 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002001 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002002 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002003 Builder.AddPlaceholderChunk("declarations");
2004 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2005 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2006 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002007 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002008
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002009 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002010 Builder.AddTypedTextChunk("namespace");
2011 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2012 Builder.AddPlaceholderChunk("name");
2013 Builder.AddChunk(CodeCompletionString::CK_Equal);
2014 Builder.AddPlaceholderChunk("namespace");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002015 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002016 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002017
2018 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002019 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2021 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002022 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002023 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002024
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002025 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002026 Builder.AddTypedTextChunk("asm");
2027 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2028 Builder.AddPlaceholderChunk("string-literal");
2029 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2030 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002031
Douglas Gregorf4c33342010-05-28 00:22:41 +00002032 if (Results.includeCodePatterns()) {
2033 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002034 Builder.AddTypedTextChunk("template");
2035 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2036 Builder.AddPlaceholderChunk("declaration");
2037 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002038 } else {
2039 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002040 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002041 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002042
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002043 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002044 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002045
Douglas Gregorf4c33342010-05-28 00:22:41 +00002046 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002047 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002048
John McCallfaf5fb42010-08-26 23:41:50 +00002049 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002050 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002051 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002052 Builder.AddTypedTextChunk("using");
2053 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2054 Builder.AddPlaceholderChunk("qualifier");
2055 Builder.AddTextChunk("::");
2056 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002057 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002058 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002059
Douglas Gregorf4c33342010-05-28 00:22:41 +00002060 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002061 if (SemaRef.CurContext->isDependentContext()) {
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002062 Builder.AddTypedTextChunk("using typename");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002063 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2064 Builder.AddPlaceholderChunk("qualifier");
2065 Builder.AddTextChunk("::");
2066 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002067 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002068 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002069 }
2070
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002071 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
2072
John McCallfaf5fb42010-08-26 23:41:50 +00002073 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002074 AddTypedefResult(Results);
2075
Erik Verbruggen6524c052017-10-24 13:46:58 +00002076 bool IsNotInheritanceScope =
2077 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002078 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002079 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002080 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002081 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002082 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002083
2084 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002085 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002086 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002087 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002088 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002089
2090 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002091 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002092 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002093 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002094 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002095
2096 // FIXME: This adds override results only if we are at the first word of
2097 // the declaration/definition. Also call this from other sides to have
2098 // more use-cases.
2099 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
2100 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002101 }
2102 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002103 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002104
John McCallfaf5fb42010-08-26 23:41:50 +00002105 case Sema::PCC_Template:
2106 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002107 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002108 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002109 Builder.AddTypedTextChunk("template");
2110 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2111 Builder.AddPlaceholderChunk("parameters");
2112 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2113 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002114 } else {
2115 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002116 }
2117
David Blaikiebbafb8a2012-03-11 07:00:24 +00002118 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2119 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002120 break;
2121
John McCallfaf5fb42010-08-26 23:41:50 +00002122 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002123 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2124 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2125 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002126 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002127
John McCallfaf5fb42010-08-26 23:41:50 +00002128 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002129 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2130 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2131 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002132 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002133
John McCallfaf5fb42010-08-26 23:41:50 +00002134 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002135 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002136 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002137
John McCallfaf5fb42010-08-26 23:41:50 +00002138 case Sema::PCC_RecoveryInFunction:
2139 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002140 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002141
David Blaikiebbafb8a2012-03-11 07:00:24 +00002142 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2143 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002144 Builder.AddTypedTextChunk("try");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002145 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002146 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002147 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002148 Builder.AddPlaceholderChunk("statements");
2149 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2150 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002151 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002152 Builder.AddTextChunk("catch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002154 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2155 Builder.AddPlaceholderChunk("declaration");
2156 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002157 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002158 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002159 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002160 Builder.AddPlaceholderChunk("statements");
2161 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2162 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2163 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002164 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002165 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002166 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002167
Douglas Gregorf64acca2010-05-25 21:41:55 +00002168 if (Results.includeCodePatterns()) {
2169 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002170 Builder.AddTypedTextChunk("if");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002171 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002172 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002173 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002174 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002175 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002176 Builder.AddPlaceholderChunk("expression");
2177 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002178 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002179 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002180 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002181 Builder.AddPlaceholderChunk("statements");
2182 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2183 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2184 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002185
Douglas Gregorf64acca2010-05-25 21:41:55 +00002186 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002187 Builder.AddTypedTextChunk("switch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002188 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002189 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002190 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002191 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002192 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002193 Builder.AddPlaceholderChunk("expression");
2194 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002195 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002196 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2197 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002198 Builder.AddPlaceholderChunk("cases");
2199 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002200 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2201 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002202 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002203
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002204 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002205 if (SemaRef.getCurFunction() &&
2206 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002207 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002208 Builder.AddTypedTextChunk("case");
2209 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2210 Builder.AddPlaceholderChunk("expression");
2211 Builder.AddChunk(CodeCompletionString::CK_Colon);
2212 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002213
2214 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002215 Builder.AddTypedTextChunk("default");
2216 Builder.AddChunk(CodeCompletionString::CK_Colon);
2217 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002218 }
2219
Douglas Gregorf64acca2010-05-25 21:41:55 +00002220 if (Results.includeCodePatterns()) {
2221 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002222 Builder.AddTypedTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002223 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002224 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002225 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002226 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002227 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002228 Builder.AddPlaceholderChunk("expression");
2229 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002230 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002231 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002232 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002233 Builder.AddPlaceholderChunk("statements");
2234 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2235 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2236 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002237
2238 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002239 Builder.AddTypedTextChunk("do");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002240 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002241 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002242 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002243 Builder.AddPlaceholderChunk("statements");
2244 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2245 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2246 Builder.AddTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002247 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002248 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2249 Builder.AddPlaceholderChunk("expression");
2250 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2251 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002252
Douglas Gregorf64acca2010-05-25 21:41:55 +00002253 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002254 Builder.AddTypedTextChunk("for");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002255 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002256 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002257 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002258 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002259 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002260 Builder.AddPlaceholderChunk("init-expression");
2261 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002262 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002263 Builder.AddPlaceholderChunk("condition");
2264 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002265 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002266 Builder.AddPlaceholderChunk("inc-expression");
2267 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002268 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002269 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2270 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2271 Builder.AddPlaceholderChunk("statements");
2272 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2273 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2274 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002275 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002276
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002277 if (S->getContinueParent()) {
2278 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002279 Builder.AddTypedTextChunk("continue");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002280 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002281 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002282 }
2283
2284 if (S->getBreakParent()) {
2285 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002286 Builder.AddTypedTextChunk("break");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002287 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002288 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002289 }
2290
Ilya Biryukov32497f52019-05-27 09:52:09 +00002291 // "return expression ;" or "return ;", depending on the return type.
2292 QualType ReturnType;
Fangrui Song050229d2018-11-24 00:14:31 +00002293 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002294 ReturnType = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002295 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002296 ReturnType = Method->getReturnType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002297 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002298 !SemaRef.getCurBlock()->ReturnType.isNull())
Ilya Biryukov32497f52019-05-27 09:52:09 +00002299 ReturnType = SemaRef.getCurBlock()->ReturnType;;
2300 if (ReturnType.isNull() || ReturnType->isVoidType()) {
2301 Builder.AddTypedTextChunk("return");
2302 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2303 Results.AddResult(Result(Builder.TakeString()));
2304 } else {
2305 assert(!ReturnType.isNull());
2306 // "return expression ;"
2307 Builder.AddTypedTextChunk("return");
2308 Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002309 Builder.AddPlaceholderChunk("expression");
Ilya Biryukov32497f52019-05-27 09:52:09 +00002310 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2311 Results.AddResult(Result(Builder.TakeString()));
2312 // When boolean, also add 'return true;' and 'return false;'.
2313 if (ReturnType->isBooleanType()) {
2314 Builder.AddTypedTextChunk("return true");
2315 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2316 Results.AddResult(Result(Builder.TakeString()));
2317
2318 Builder.AddTypedTextChunk("return false");
2319 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2320 Results.AddResult(Result(Builder.TakeString()));
2321 }
Ilya Biryukov57a51b62020-01-10 11:50:27 +01002322 // For pointers, suggest 'return nullptr' in C++.
2323 if (SemaRef.getLangOpts().CPlusPlus11 &&
2324 (ReturnType->isPointerType() || ReturnType->isMemberPointerType())) {
2325 Builder.AddTypedTextChunk("return nullptr");
2326 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2327 Results.AddResult(Result(Builder.TakeString()));
2328 }
Douglas Gregor44272ca2010-02-18 04:06:48 +00002329 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002330
Douglas Gregorf4c33342010-05-28 00:22:41 +00002331 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002332 Builder.AddTypedTextChunk("goto");
2333 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2334 Builder.AddPlaceholderChunk("label");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002335 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002336 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002337
Douglas Gregorf4c33342010-05-28 00:22:41 +00002338 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002339 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002340 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2341 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002342 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002343 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002344
2345 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002346 }
Fangrui Song050229d2018-11-24 00:14:31 +00002347 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002348
2349 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002350 case Sema::PCC_ForInit:
2351 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002352 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002353 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002354 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002355
Douglas Gregor5e35d592010-09-14 23:59:36 +00002356 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002357 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002358 CCC == Sema::PCC_ParenthesizedExpression) {
2359 // (__bridge <type>)<expression>
2360 Builder.AddTypedTextChunk("__bridge");
2361 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2362 Builder.AddPlaceholderChunk("type");
2363 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2364 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002365 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002366
2367 // (__bridge_transfer <Objective-C type>)<expression>
2368 Builder.AddTypedTextChunk("__bridge_transfer");
2369 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2370 Builder.AddPlaceholderChunk("Objective-C type");
2371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2372 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002373 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002374
2375 // (__bridge_retained <CF type>)<expression>
2376 Builder.AddTypedTextChunk("__bridge_retained");
2377 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2378 Builder.AddPlaceholderChunk("CF type");
2379 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2380 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002381 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002382 }
2383 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002384 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002385
John McCallfaf5fb42010-08-26 23:41:50 +00002386 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002387 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002388 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002389 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002390
Douglas Gregore5c79d52011-10-18 21:20:17 +00002391 // true
2392 Builder.AddResultTypeChunk("bool");
2393 Builder.AddTypedTextChunk("true");
2394 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002395
Douglas Gregore5c79d52011-10-18 21:20:17 +00002396 // false
2397 Builder.AddResultTypeChunk("bool");
2398 Builder.AddTypedTextChunk("false");
2399 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002400
David Blaikiebbafb8a2012-03-11 07:00:24 +00002401 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002402 // dynamic_cast < type-id > ( expression )
2403 Builder.AddTypedTextChunk("dynamic_cast");
2404 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2405 Builder.AddPlaceholderChunk("type");
2406 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2407 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2408 Builder.AddPlaceholderChunk("expression");
2409 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002410 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002411 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002412
Douglas Gregorf4c33342010-05-28 00:22:41 +00002413 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002414 Builder.AddTypedTextChunk("static_cast");
2415 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2416 Builder.AddPlaceholderChunk("type");
2417 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2419 Builder.AddPlaceholderChunk("expression");
2420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002421 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002422
Douglas Gregorf4c33342010-05-28 00:22:41 +00002423 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002424 Builder.AddTypedTextChunk("reinterpret_cast");
2425 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2426 Builder.AddPlaceholderChunk("type");
2427 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2428 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2429 Builder.AddPlaceholderChunk("expression");
2430 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002431 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002432
Douglas Gregorf4c33342010-05-28 00:22:41 +00002433 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002434 Builder.AddTypedTextChunk("const_cast");
2435 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2436 Builder.AddPlaceholderChunk("type");
2437 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2438 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2439 Builder.AddPlaceholderChunk("expression");
2440 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002441 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002442
David Blaikiebbafb8a2012-03-11 07:00:24 +00002443 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002444 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002445 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002446 Builder.AddTypedTextChunk("typeid");
2447 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2448 Builder.AddPlaceholderChunk("expression-or-type");
2449 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002450 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002451 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002452
Douglas Gregorf4c33342010-05-28 00:22:41 +00002453 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002454 Builder.AddTypedTextChunk("new");
2455 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2456 Builder.AddPlaceholderChunk("type");
2457 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2458 Builder.AddPlaceholderChunk("expressions");
2459 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002460 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002461
Douglas Gregorf4c33342010-05-28 00:22:41 +00002462 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002463 Builder.AddTypedTextChunk("new");
2464 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2465 Builder.AddPlaceholderChunk("type");
2466 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2467 Builder.AddPlaceholderChunk("size");
2468 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2469 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2470 Builder.AddPlaceholderChunk("expressions");
2471 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002472 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002473
Douglas Gregorf4c33342010-05-28 00:22:41 +00002474 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002475 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002476 Builder.AddTypedTextChunk("delete");
2477 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2478 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002479 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002480
Douglas Gregorf4c33342010-05-28 00:22:41 +00002481 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002482 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002483 Builder.AddTypedTextChunk("delete");
2484 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2485 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2486 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2487 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2488 Builder.AddPlaceholderChunk("expression");
2489 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002490
David Blaikiebbafb8a2012-03-11 07:00:24 +00002491 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002492 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002493 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002494 Builder.AddTypedTextChunk("throw");
2495 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2496 Builder.AddPlaceholderChunk("expression");
2497 Results.AddResult(Result(Builder.TakeString()));
2498 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002499
Douglas Gregora2db7932010-05-26 22:00:08 +00002500 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002501
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002502 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002503 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002504 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002505 Builder.AddTypedTextChunk("nullptr");
2506 Results.AddResult(Result(Builder.TakeString()));
2507
2508 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002509 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002510 Builder.AddTypedTextChunk("alignof");
2511 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2512 Builder.AddPlaceholderChunk("type");
2513 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2514 Results.AddResult(Result(Builder.TakeString()));
2515
2516 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002517 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002518 Builder.AddTypedTextChunk("noexcept");
2519 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2520 Builder.AddPlaceholderChunk("expression");
2521 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2522 Results.AddResult(Result(Builder.TakeString()));
2523
2524 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002525 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002526 Builder.AddTypedTextChunk("sizeof...");
2527 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2528 Builder.AddPlaceholderChunk("parameter-pack");
2529 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2530 Results.AddResult(Result(Builder.TakeString()));
2531 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002532 }
2533
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002534 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002535 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002536 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2537 // The interface can be NULL.
2538 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002539 if (ID->getSuperClass()) {
2540 std::string SuperType;
2541 SuperType = ID->getSuperClass()->getNameAsString();
2542 if (Method->isInstanceMethod())
2543 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002544
Douglas Gregore5c79d52011-10-18 21:20:17 +00002545 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2546 Builder.AddTypedTextChunk("super");
2547 Results.AddResult(Result(Builder.TakeString()));
2548 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002549 }
2550
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002551 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002552 }
2553
Jordan Rose58d54722012-06-30 21:33:57 +00002554 if (SemaRef.getLangOpts().C11) {
2555 // _Alignof
2556 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002557 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002558 Builder.AddTypedTextChunk("alignof");
2559 else
2560 Builder.AddTypedTextChunk("_Alignof");
2561 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2562 Builder.AddPlaceholderChunk("type");
2563 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2564 Results.AddResult(Result(Builder.TakeString()));
2565 }
2566
Douglas Gregorf4c33342010-05-28 00:22:41 +00002567 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002568 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002569 Builder.AddTypedTextChunk("sizeof");
2570 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2571 Builder.AddPlaceholderChunk("expression-or-type");
2572 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2573 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002574 break;
2575 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002576
John McCallfaf5fb42010-08-26 23:41:50 +00002577 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002578 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002579 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002580 }
2581
David Blaikiebbafb8a2012-03-11 07:00:24 +00002582 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2583 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002584
David Blaikiebbafb8a2012-03-11 07:00:24 +00002585 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002586 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002587}
2588
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002589/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002590/// type chunk.
2591static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002592 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002593 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002594 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002595 if (!ND)
2596 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002597
2598 // Skip constructors and conversion functions, which have their return types
2599 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002600 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002601 return;
2602
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002603 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002604 QualType T;
2605 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002606 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002607 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002608 if (!BaseType.isNull())
2609 T = Method->getSendResultType(BaseType);
2610 else
2611 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002612 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002613 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002614 T = clang::TypeName::getFullyQualifiedType(T, Context);
2615 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002616 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002617 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002618 if (!BaseType.isNull())
2619 T = Ivar->getUsageType(BaseType);
2620 else
2621 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002622 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002623 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002624 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002625 if (!BaseType.isNull())
2626 T = Property->getUsageType(BaseType);
2627 else
2628 T = Property->getType();
2629 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002630
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002631 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2632 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002633
Fangrui Song050229d2018-11-24 00:14:31 +00002634 Result.AddResultTypeChunk(
2635 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002636}
2637
Richard Smith20e883e2015-04-29 23:20:19 +00002638static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002639 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002640 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002641 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2642 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002643 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002644 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002645 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002646 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002647 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002648 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002649 }
2650}
2651
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002652static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002653 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002654 std::string Result;
2655 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002656 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002657 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002658 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002659 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002660 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002661 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002662 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002663 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002664 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002665 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002666 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002667 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2668 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2669 switch (*nullability) {
2670 case NullabilityKind::NonNull:
2671 Result += "nonnull ";
2672 break;
2673
2674 case NullabilityKind::Nullable:
2675 Result += "nullable ";
2676 break;
2677
2678 case NullabilityKind::Unspecified:
2679 Result += "null_unspecified ";
2680 break;
2681 }
2682 }
2683 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002684 return Result;
2685}
2686
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002687/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002688/// block placeholder.
2689///
2690/// This function ignores things like typedefs and qualifiers in order to
2691/// present the most relevant and accurate block placeholders in code completion
2692/// results.
2693static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2694 FunctionTypeLoc &Block,
2695 FunctionProtoTypeLoc &BlockProto,
2696 bool SuppressBlock = false) {
2697 if (!TSInfo)
2698 return;
2699 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2700 while (true) {
2701 // Look through typedefs.
2702 if (!SuppressBlock) {
2703 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2704 if (TypeSourceInfo *InnerTSInfo =
2705 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2706 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2707 continue;
2708 }
2709 }
2710
2711 // Look through qualified types
2712 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2713 TL = QualifiedTL.getUnqualifiedLoc();
2714 continue;
2715 }
2716
2717 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2718 TL = AttrTL.getModifiedLoc();
2719 continue;
2720 }
2721 }
2722
2723 // Try to get the function prototype behind the block pointer type,
2724 // then we're done.
2725 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2726 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2727 Block = TL.getAs<FunctionTypeLoc>();
2728 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2729 }
2730 break;
2731 }
2732}
2733
Alex Lorenz920ae142016-10-18 10:38:58 +00002734static std::string
2735formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2736 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002737 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002738 bool SuppressBlock = false,
2739 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2740
Fangrui Song050229d2018-11-24 00:14:31 +00002741static std::string
2742FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2743 bool SuppressName = false, bool SuppressBlock = false,
2744 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Sam McCallbc7ff892019-04-04 11:34:18 +00002745 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.
2746 // It would be better to pass in the param Type, which is usually avaliable.
2747 // But this case is rare, so just pretend we fell back to int as elsewhere.
2748 if (!Param)
2749 return "int";
Douglas Gregore90dd002010-08-24 16:15:59 +00002750 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2751 if (Param->getType()->isDependentType() ||
2752 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002753 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002754 // containing that parameter's type.
2755 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002756
Douglas Gregor981a0c42010-08-29 19:47:46 +00002757 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Benjamin Krameradcd0262020-01-28 20:23:46 +01002758 Result = std::string(Param->getIdentifier()->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002759
Douglas Gregor86b42682015-06-19 18:27:52 +00002760 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002761 if (ObjCSubsts)
2762 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2763 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002764 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002765 Result =
2766 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002767 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002768 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002769 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002770 } else {
2771 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002772 }
2773 return Result;
2774 }
Alex Lorenza1951202016-10-18 10:35:27 +00002775
Douglas Gregore90dd002010-08-24 16:15:59 +00002776 // The argument for a block pointer parameter is a block literal with
2777 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002778 FunctionTypeLoc Block;
2779 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002780 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2781 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002782 // Try to retrieve the block type information from the property if this is a
2783 // parameter in a setter.
2784 if (!Block && ObjCMethodParam &&
2785 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2786 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2787 ->findPropertyDecl(/*CheckOverrides=*/false))
2788 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2789 SuppressBlock);
2790 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002791
2792 if (!Block) {
2793 // We were unable to find a FunctionProtoTypeLoc with parameter names
2794 // for the block; just use the parameter type as a placeholder.
2795 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002796 if (!ObjCMethodParam && Param->getIdentifier())
Benjamin Krameradcd0262020-01-28 20:23:46 +01002797 Result = std::string(Param->getIdentifier()->getName());
Douglas Gregord793e7c2011-10-18 04:23:19 +00002798
Douglas Gregor86b42682015-06-19 18:27:52 +00002799 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002800
Douglas Gregore90dd002010-08-24 16:15:59 +00002801 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002802 Result = Type.getAsString(Policy);
2803 std::string Quals =
2804 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2805 if (!Quals.empty())
2806 Result = "(" + Quals + " " + Result + ")";
2807 if (Result.back() != ')')
2808 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002809 if (Param->getIdentifier())
2810 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002811 } else {
2812 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002813 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002814
Douglas Gregore90dd002010-08-24 16:15:59 +00002815 return Result;
2816 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002817
Douglas Gregore90dd002010-08-24 16:15:59 +00002818 // We have the function prototype behind the block pointer type, as it was
2819 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002820 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2821 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002822 ObjCSubsts);
2823}
2824
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002825/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002826/// declaration.
2827///
2828/// \param BlockDecl A declaration with an Objective-C block type.
2829///
2830/// \param Block The most relevant type location for that block type.
2831///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002832/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002833/// declaration is included in the resulting string.
2834static std::string
2835formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2836 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002837 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002838 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002839 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002840 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002841 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002842 ResultType =
2843 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2844 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002845 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002846 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002847
2848 // Format the parameter list.
2849 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002850 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002851 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002852 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002853 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002854 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002855 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002856 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002857 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002858 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002859 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002860 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002861 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002862 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002863
David Blaikie6adc78e2013-02-18 22:06:02 +00002864 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002865 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002866 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002867 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002868 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002869
Douglas Gregord793e7c2011-10-18 04:23:19 +00002870 if (SuppressBlock) {
2871 // Format as a parameter.
2872 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002873 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002874 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002875 Result += ")";
2876 Result += Params;
2877 } else {
2878 // Format as a block literal argument.
2879 Result = '^' + Result;
2880 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002881
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002882 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002883 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002884 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002885
Douglas Gregore90dd002010-08-24 16:15:59 +00002886 return Result;
2887}
2888
Erik Verbruggen11338c52017-07-19 10:45:40 +00002889static std::string GetDefaultValueString(const ParmVarDecl *Param,
2890 const SourceManager &SM,
2891 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002892 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002893 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2894 bool Invalid = CharSrcRange.isInvalid();
2895 if (Invalid)
2896 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002897 StringRef srcText =
2898 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002899 if (Invalid)
2900 return "";
2901
2902 if (srcText.empty() || srcText == "=") {
2903 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002904 // This happens if the code is incorrect (for example class is forward
2905 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002906 return "";
2907 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002908 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002909 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2910 // this value always has (or always does not have) '=' in front of it
2911 if (DefValue.at(0) != '=') {
2912 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002913 // Lexer returns built-in types values without '=' and user-defined types
2914 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002915 return " = " + DefValue;
2916 }
2917 return " " + DefValue;
2918}
2919
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002920/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002921static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002922 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002923 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002924 CodeCompletionBuilder &Result,
2925 unsigned Start = 0,
2926 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002927 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002928
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002929 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002930 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002931
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002932 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002933 // When we see an optional default argument, put that argument and
2934 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002935 CodeCompletionBuilder Opt(Result.getAllocator(),
2936 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002937 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002938 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002939 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002940 Result.AddOptionalChunk(Opt.TakeString());
2941 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002942 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002943
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002944 if (FirstParameter)
2945 FirstParameter = false;
2946 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002947 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002948
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002949 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002950
Douglas Gregor3545ff42009-09-21 16:56:56 +00002951 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002952 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002953 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002954 PlaceholderStr +=
2955 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002956
Douglas Gregor400f5972010-08-31 05:13:43 +00002957 if (Function->isVariadic() && P == N - 1)
2958 PlaceholderStr += ", ...";
2959
Douglas Gregor3545ff42009-09-21 16:56:56 +00002960 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002961 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002962 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002963 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002964
Fangrui Song050229d2018-11-24 00:14:31 +00002965 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002966 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002967 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002968 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002969
Richard Smith20e883e2015-04-29 23:20:19 +00002970 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002971 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002972}
2973
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002974/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002975static void AddTemplateParameterChunks(
2976 ASTContext &Context, const PrintingPolicy &Policy,
2977 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2978 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002979 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002980
2981 // Prefer to take the template parameter names from the first declaration of
2982 // the template.
2983 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2984
Douglas Gregor3545ff42009-09-21 16:56:56 +00002985 TemplateParameterList *Params = Template->getTemplateParameters();
2986 TemplateParameterList::iterator PEnd = Params->end();
2987 if (MaxParameters)
2988 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002989 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2990 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002991 bool HasDefaultArg = false;
2992 std::string PlaceholderStr;
2993 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2994 if (TTP->wasDeclaredWithTypename())
2995 PlaceholderStr = "typename";
Saar Razff1e0fc2020-01-15 02:48:42 +02002996 else if (const auto *TC = TTP->getTypeConstraint()) {
2997 llvm::raw_string_ostream OS(PlaceholderStr);
2998 TC->print(OS, Policy);
2999 OS.flush();
3000 } else
Douglas Gregor3545ff42009-09-21 16:56:56 +00003001 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003002
Douglas Gregor3545ff42009-09-21 16:56:56 +00003003 if (TTP->getIdentifier()) {
3004 PlaceholderStr += ' ';
3005 PlaceholderStr += TTP->getIdentifier()->getName();
3006 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003007
Douglas Gregor3545ff42009-09-21 16:56:56 +00003008 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003009 } else if (NonTypeTemplateParmDecl *NTTP =
3010 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003011 if (NTTP->getIdentifier())
Benjamin Krameradcd0262020-01-28 20:23:46 +01003012 PlaceholderStr = std::string(NTTP->getIdentifier()->getName());
John McCall31168b02011-06-15 23:02:42 +00003013 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003014 HasDefaultArg = NTTP->hasDefaultArgument();
3015 } else {
3016 assert(isa<TemplateTemplateParmDecl>(*P));
3017 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003018
Douglas Gregor3545ff42009-09-21 16:56:56 +00003019 // Since putting the template argument list into the placeholder would
3020 // be very, very long, we just use an abbreviation.
3021 PlaceholderStr = "template<...> class";
3022 if (TTP->getIdentifier()) {
3023 PlaceholderStr += ' ';
3024 PlaceholderStr += TTP->getIdentifier()->getName();
3025 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003026
Douglas Gregor3545ff42009-09-21 16:56:56 +00003027 HasDefaultArg = TTP->hasDefaultArgument();
3028 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003029
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003030 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003031 // When we see an optional default argument, put that argument and
3032 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003033 CodeCompletionBuilder Opt(Result.getAllocator(),
3034 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003035 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003036 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00003037 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003038 P - Params->begin(), true);
3039 Result.AddOptionalChunk(Opt.TakeString());
3040 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003041 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003042
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003043 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003044
Douglas Gregor3545ff42009-09-21 16:56:56 +00003045 if (FirstParameter)
3046 FirstParameter = false;
3047 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003048 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003049
Douglas Gregor3545ff42009-09-21 16:56:56 +00003050 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003051 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003052 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003053 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003054}
3055
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003056/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00003057/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00003058static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
3059 NestedNameSpecifier *Qualifier,
3060 bool QualifierIsInformative,
3061 ASTContext &Context,
3062 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003063 if (!Qualifier)
3064 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003065
Douglas Gregorf2510672009-09-21 19:57:38 +00003066 std::string PrintedNNS;
3067 {
3068 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00003069 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00003070 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00003071 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003072 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00003073 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003074 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00003075}
3076
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003077static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003078AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003079 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00003080 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003081 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00003082 return;
3083
Douglas Gregor304f9b02011-02-01 21:15:40 +00003084 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003085
Douglas Gregor304f9b02011-02-01 21:15:40 +00003086 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003087 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003088 Result.AddInformativeChunk(" const");
3089 return;
3090 }
3091
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003092 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003093 Result.AddInformativeChunk(" volatile");
3094 return;
3095 }
3096
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003097 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003098 Result.AddInformativeChunk(" restrict");
3099 return;
3100 }
3101
3102 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00003103 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00003104 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00003105 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00003106 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00003107 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00003108 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00003109 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003110 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00003111}
3112
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003113/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00003114static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003115 const NamedDecl *ND,
3116 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00003117 DeclarationName Name = ND->getDeclName();
3118 if (!Name)
3119 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003120
Douglas Gregor0212fd72010-09-21 16:06:22 +00003121 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003122 case DeclarationName::CXXOperatorName: {
3123 const char *OperatorName = nullptr;
3124 switch (Name.getCXXOverloadedOperator()) {
3125 case OO_None:
3126 case OO_Conditional:
3127 case NUM_OVERLOADED_OPERATORS:
3128 OperatorName = "operator";
3129 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003130
Fangrui Song050229d2018-11-24 00:14:31 +00003131#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
3132 case OO_##Name: \
3133 OperatorName = "operator" Spelling; \
3134 break;
3135#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00003136#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003137
Fangrui Song050229d2018-11-24 00:14:31 +00003138 case OO_New:
3139 OperatorName = "operator new";
3140 break;
3141 case OO_Delete:
3142 OperatorName = "operator delete";
3143 break;
3144 case OO_Array_New:
3145 OperatorName = "operator new[]";
3146 break;
3147 case OO_Array_Delete:
3148 OperatorName = "operator delete[]";
3149 break;
3150 case OO_Call:
3151 OperatorName = "operator()";
3152 break;
3153 case OO_Subscript:
3154 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003155 break;
3156 }
Fangrui Song050229d2018-11-24 00:14:31 +00003157 Result.AddTypedTextChunk(OperatorName);
3158 break;
3159 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003160
Douglas Gregor0212fd72010-09-21 16:06:22 +00003161 case DeclarationName::Identifier:
3162 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003163 case DeclarationName::CXXDestructorName:
3164 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003165 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003166 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003167 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003168
Richard Smith35845152017-02-07 01:37:30 +00003169 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003170 case DeclarationName::CXXUsingDirective:
3171 case DeclarationName::ObjCZeroArgSelector:
3172 case DeclarationName::ObjCOneArgSelector:
3173 case DeclarationName::ObjCMultiArgSelector:
3174 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003175
Douglas Gregor0212fd72010-09-21 16:06:22 +00003176 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003177 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003178 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003179 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003180 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003181 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003182 Record = InjectedTy->getDecl();
3183 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003184 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003185 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003186 break;
3187 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003188
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003189 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003190 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003191 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003192 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003193 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003194 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003195 }
3196 break;
3197 }
3198 }
3199}
3200
Fangrui Song050229d2018-11-24 00:14:31 +00003201CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3202 Sema &S, const CodeCompletionContext &CCContext,
3203 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3204 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003205 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3206 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003207}
3208
Eric Liu00f43c92018-07-06 09:43:57 +00003209CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3210 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3211 CodeCompletionTUInfo &CCTUInfo) {
3212 assert(Kind == RK_Macro);
3213 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3214 const MacroInfo *MI = PP.getMacroInfo(Macro);
3215 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3216
3217 if (!MI || !MI->isFunctionLike())
3218 return Result.TakeString();
3219
3220 // Format a function-like macro with placeholders for the arguments.
3221 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3222 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3223
3224 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3225 if (MI->isC99Varargs()) {
3226 --AEnd;
3227
3228 if (A == AEnd) {
3229 Result.AddPlaceholderChunk("...");
3230 }
3231 }
3232
3233 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3234 if (A != MI->param_begin())
3235 Result.AddChunk(CodeCompletionString::CK_Comma);
3236
3237 if (MI->isVariadic() && (A + 1) == AEnd) {
3238 SmallString<32> Arg = (*A)->getName();
3239 if (MI->isC99Varargs())
3240 Arg += ", ...";
3241 else
3242 Arg += "...";
3243 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3244 break;
3245 }
3246
3247 // Non-variadic macros are simple.
3248 Result.AddPlaceholderChunk(
3249 Result.getAllocator().CopyString((*A)->getName()));
3250 }
3251 Result.AddChunk(CodeCompletionString::CK_RightParen);
3252 return Result.TakeString();
3253}
3254
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003255/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003256/// result.
3257///
3258/// \returns Either a new, heap-allocated code completion string describing
3259/// how to use this result, or NULL to indicate that the string or name of the
3260/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003261CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3262 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3263 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3264 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003265 if (Kind == RK_Macro)
3266 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3267
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003268 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003269
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003270 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003271 if (Kind == RK_Pattern) {
3272 Pattern->Priority = Priority;
3273 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003274
Douglas Gregor78254c82012-03-27 23:34:16 +00003275 if (Declaration) {
3276 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003277 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003278 if (const RawComment *RC =
3279 getPatternCompletionComment(Ctx, Declaration)) {
3280 Result.addBriefComment(RC->getBriefText(Ctx));
3281 Pattern->BriefComment = Result.getBriefComment();
3282 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003283 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003284
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003285 return Pattern;
3286 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003287
Douglas Gregorf09935f2009-12-01 05:55:20 +00003288 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003289 Result.AddTypedTextChunk(Keyword);
3290 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003291 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003292 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003293 return createCodeCompletionStringForDecl(
3294 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003295}
3296
Ilya Biryukovcabab292019-05-24 10:18:39 +00003297static void printOverrideString(const CodeCompletionString &CCS,
3298 std::string &BeforeName,
3299 std::string &NameAndSignature) {
3300 bool SeenTypedChunk = false;
3301 for (auto &Chunk : CCS) {
3302 if (Chunk.Kind == CodeCompletionString::CK_Optional) {
3303 assert(SeenTypedChunk && "optional parameter before name");
3304 // Note that we put all chunks inside into NameAndSignature.
3305 printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature);
3306 continue;
3307 }
3308 SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText;
3309 if (SeenTypedChunk)
3310 NameAndSignature += Chunk.Text;
3311 else
3312 BeforeName += Chunk.Text;
3313 }
3314}
3315
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003316CodeCompletionString *
3317CodeCompletionResult::createCodeCompletionStringForOverride(
3318 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3319 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3320 PrintingPolicy &Policy) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003321 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3322 /*IncludeBriefComments=*/false,
3323 CCContext, Policy);
Ilya Biryukovcabab292019-05-24 10:18:39 +00003324 std::string BeforeName;
3325 std::string NameAndSignature;
3326 // For overrides all chunks go into the result, none are informative.
3327 printOverrideString(*CCS, BeforeName, NameAndSignature);
3328 NameAndSignature += " override";
3329
3330 Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));
3331 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3332 Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003333 return Result.TakeString();
3334}
3335
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003336// FIXME: Right now this works well with lambdas. Add support for other functor
3337// types like std::function.
3338static const NamedDecl *extractFunctorCallOperator(const NamedDecl *ND) {
3339 const auto *VD = dyn_cast<VarDecl>(ND);
3340 if (!VD)
3341 return nullptr;
3342 const auto *RecordDecl = VD->getType()->getAsCXXRecordDecl();
3343 if (!RecordDecl || !RecordDecl->isLambda())
3344 return nullptr;
3345 return RecordDecl->getLambdaCallOperator();
3346}
3347
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003348CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3349 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3350 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3351 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003352 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003353 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003354
3355 if (IncludeBriefComments) {
3356 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003357 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003358 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003359 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003360 }
3361
Douglas Gregor9eb77012009-11-07 00:00:49 +00003362 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003363 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003364 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003365 Result.AddTextChunk("::");
3366 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003367 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003368
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003369 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3370 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003371
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003372 auto AddFunctionTypeAndResult = [&](const FunctionDecl *Function) {
3373 AddResultTypeChunk(Ctx, Policy, Function, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003374 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003375 Ctx, Policy);
3376 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003377 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003378 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003379 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003380 AddFunctionTypeQualsToCompletionString(Result, Function);
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003381 };
3382
3383 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
3384 AddFunctionTypeAndResult(Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003385 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003386 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003387
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003388 if (const auto *CallOperator =
3389 dyn_cast_or_null<FunctionDecl>(extractFunctorCallOperator(ND))) {
3390 AddFunctionTypeAndResult(CallOperator);
3391 return Result.TakeString();
3392 }
3393
3394 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
3395
Fangrui Song050229d2018-11-24 00:14:31 +00003396 if (const FunctionTemplateDecl *FunTmpl =
3397 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003398 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003399 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003400 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003401 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003402
Douglas Gregor3545ff42009-09-21 16:56:56 +00003403 // Figure out which template parameters are deduced (or have default
3404 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003405 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003406 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003407 unsigned LastDeducibleArgument;
3408 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3409 --LastDeducibleArgument) {
3410 if (!Deduced[LastDeducibleArgument - 1]) {
3411 // C++0x: Figure out if the template argument has a default. If so,
3412 // the user doesn't need to type this argument.
3413 // FIXME: We need to abstract template parameters better!
3414 bool HasDefaultArg = false;
3415 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003416 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003417 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3418 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003419 else if (NonTypeTemplateParmDecl *NTTP =
3420 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003421 HasDefaultArg = NTTP->hasDefaultArgument();
3422 else {
3423 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003424 HasDefaultArg =
3425 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003426 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003427
Douglas Gregor3545ff42009-09-21 16:56:56 +00003428 if (!HasDefaultArg)
3429 break;
3430 }
3431 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003432
Douglas Gregor3545ff42009-09-21 16:56:56 +00003433 if (LastDeducibleArgument) {
3434 // Some of the function template arguments cannot be deduced from a
3435 // function call, so we introduce an explicit template argument list
3436 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003437 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003438 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003439 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003440 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003441 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003442
Douglas Gregor3545ff42009-09-21 16:56:56 +00003443 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003444 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003445 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003446 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003447 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003448 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003449 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003450
Fangrui Song050229d2018-11-24 00:14:31 +00003451 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003452 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003453 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003454 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003455 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003456 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003457 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003458 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003459 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003460 }
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003461
Fangrui Song050229d2018-11-24 00:14:31 +00003462 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003463 Selector Sel = Method->getSelector();
3464 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003465 Result.AddTypedTextChunk(
3466 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003467 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003468 }
3469
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003470 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003471 SelName += ':';
3472 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003473 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003474 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003475 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003476
Douglas Gregor1b605f72009-11-19 01:08:35 +00003477 // If there is only one parameter, and we're past it, add an empty
3478 // typed-text chunk since there is nothing to type.
3479 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003480 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003481 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003482 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003483 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003484 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003485 P != PEnd; (void)++P, ++Idx) {
3486 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003487 std::string Keyword;
3488 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003489 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003490 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003491 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003492 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003493 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003494 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003495 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003496 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003497 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003498
Douglas Gregor1b605f72009-11-19 01:08:35 +00003499 // If we're before the starting parameter, skip the placeholder.
3500 if (Idx < StartParameter)
3501 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003502
3503 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003504 QualType ParamType = (*P)->getType();
3505 Optional<ArrayRef<QualType>> ObjCSubsts;
3506 if (!CCContext.getBaseType().isNull())
3507 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3508
3509 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3510 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003511 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003512 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003513 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003514 ParamType = ParamType.substObjCTypeArgs(
3515 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003516 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003517 ParamType);
3518 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003519 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003520 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003521 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003522 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003523
Douglas Gregor400f5972010-08-31 05:13:43 +00003524 if (Method->isVariadic() && (P + 1) == PEnd)
3525 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003526
Douglas Gregor95887f92010-07-08 23:20:03 +00003527 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003528 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003529 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003530 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003531 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003532 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003533 }
3534
Douglas Gregor04c5f972009-12-23 00:21:46 +00003535 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003536 if (Method->param_size() == 0) {
3537 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003538 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003539 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003540 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003541 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003542 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003543 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003544
Richard Smith20e883e2015-04-29 23:20:19 +00003545 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003546 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003547
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003548 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003549 }
3550
Douglas Gregorf09935f2009-12-01 05:55:20 +00003551 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003552 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003553 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003554
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003555 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003556 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003557 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003558}
3559
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003560const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3561 const NamedDecl *ND) {
3562 if (!ND)
3563 return nullptr;
3564 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3565 return RC;
3566
3567 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003568 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003569 if (!M)
3570 return nullptr;
3571 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3572 if (!PDecl)
3573 return nullptr;
3574
3575 return Ctx.getRawCommentForAnyRedecl(PDecl);
3576}
3577
3578const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3579 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003580 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003581 if (!M || !M->isPropertyAccessor())
3582 return nullptr;
3583
3584 // Provide code completion comment for self.GetterName where
3585 // GetterName is the getter method for a property with name
3586 // different from the property name (declared via a property
3587 // getter attribute.
3588 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3589 if (!PDecl)
3590 return nullptr;
3591 if (PDecl->getGetterName() == M->getSelector() &&
3592 PDecl->getIdentifier() != M->getIdentifier()) {
3593 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3594 return RC;
3595 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3596 return RC;
3597 }
3598 return nullptr;
3599}
3600
3601const RawComment *clang::getParameterComment(
3602 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003603 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003604 auto FDecl = Result.getFunction();
3605 if (!FDecl)
3606 return nullptr;
3607 if (ArgIndex < FDecl->getNumParams())
3608 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3609 return nullptr;
3610}
3611
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003612/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003613/// string.
3614static void AddOverloadParameterChunks(ASTContext &Context,
3615 const PrintingPolicy &Policy,
3616 const FunctionDecl *Function,
3617 const FunctionProtoType *Prototype,
3618 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003619 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003620 bool InOptional = false) {
3621 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003622 unsigned NumParams =
3623 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003624
3625 for (unsigned P = Start; P != NumParams; ++P) {
3626 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3627 // When we see an optional default argument, put that argument and
3628 // the remaining default arguments into a new, optional string.
3629 CodeCompletionBuilder Opt(Result.getAllocator(),
3630 Result.getCodeCompletionTUInfo());
3631 if (!FirstParameter)
3632 Opt.AddChunk(CodeCompletionString::CK_Comma);
3633 // Optional sections are nested.
3634 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3635 CurrentArg, P, /*InOptional=*/true);
3636 Result.AddOptionalChunk(Opt.TakeString());
3637 return;
3638 }
3639
3640 if (FirstParameter)
3641 FirstParameter = false;
3642 else
3643 Result.AddChunk(CodeCompletionString::CK_Comma);
3644
3645 InOptional = false;
3646
3647 // Format the placeholder string.
3648 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003649 if (Function) {
3650 const ParmVarDecl *Param = Function->getParamDecl(P);
3651 Placeholder = FormatFunctionParameter(Policy, Param);
3652 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003653 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3654 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003655 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003656 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003657 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003658
3659 if (P == CurrentArg)
3660 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003661 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003662 else
3663 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3664 }
3665
3666 if (Prototype && Prototype->isVariadic()) {
3667 CodeCompletionBuilder Opt(Result.getAllocator(),
3668 Result.getCodeCompletionTUInfo());
3669 if (!FirstParameter)
3670 Opt.AddChunk(CodeCompletionString::CK_Comma);
3671
3672 if (CurrentArg < NumParams)
3673 Opt.AddPlaceholderChunk("...");
3674 else
3675 Opt.AddCurrentParameterChunk("...");
3676
3677 Result.AddOptionalChunk(Opt.TakeString());
3678 }
3679}
3680
Douglas Gregorf0f51982009-09-23 00:34:09 +00003681CodeCompletionString *
3682CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003683 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3684 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003685 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Sam McCallfa3b87f2019-11-15 14:52:04 +01003686 // Show signatures of constructors as they are declared:
3687 // vector(int n) rather than vector<string>(int n)
3688 // This is less noisy without being less clear, and avoids tricky cases.
3689 Policy.SuppressTemplateArgsInCXXConstructors = true;
John McCall31168b02011-06-15 23:02:42 +00003690
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003691 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003692 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3693 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003694 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003695 const FunctionProtoType *Proto =
3696 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003697 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003698 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003699 // highlighted ellipsis.
3700 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003701 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003702 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003703 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3704 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3705 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003706 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003707 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003708
3709 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003710 if (IncludeBriefComments) {
3711 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003712 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003713 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003714 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Kadir Cetinkaya1f946ee2020-01-13 09:00:19 +01003715
3716 std::string Name;
3717 llvm::raw_string_ostream OS(Name);
3718 FDecl->getDeclName().print(OS, Policy);
3719 Result.AddTextChunk(Result.getAllocator().CopyString(OS.str()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003720 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003721 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003722 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003723 }
Alp Toker314cc812014-01-25 16:55:45 +00003724
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003725 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003726 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3727 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003728 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003729
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003730 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003731}
3732
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003733unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003734 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003735 bool PreferredTypeIsPointer) {
3736 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003737
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003738 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003739 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003740 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003741 Priority = CCP_Constant;
3742 if (PreferredTypeIsPointer)
3743 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003744 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003745 // Treat "YES", "NO", "true", and "false" as constants.
3746 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3747 MacroName.equals("true") || MacroName.equals("false"))
3748 Priority = CCP_Constant;
3749 // Treat "bool" as a type.
3750 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003751 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003752
Douglas Gregor6e240332010-08-16 16:18:59 +00003753 return Priority;
3754}
3755
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003756CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003757 if (!D)
3758 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003759
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003760 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003761 case Decl::Enum:
3762 return CXCursor_EnumDecl;
3763 case Decl::EnumConstant:
3764 return CXCursor_EnumConstantDecl;
3765 case Decl::Field:
3766 return CXCursor_FieldDecl;
3767 case Decl::Function:
3768 return CXCursor_FunctionDecl;
3769 case Decl::ObjCCategory:
3770 return CXCursor_ObjCCategoryDecl;
3771 case Decl::ObjCCategoryImpl:
3772 return CXCursor_ObjCCategoryImplDecl;
3773 case Decl::ObjCImplementation:
3774 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003775
Fangrui Song050229d2018-11-24 00:14:31 +00003776 case Decl::ObjCInterface:
3777 return CXCursor_ObjCInterfaceDecl;
3778 case Decl::ObjCIvar:
3779 return CXCursor_ObjCIvarDecl;
3780 case Decl::ObjCMethod:
3781 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3782 ? CXCursor_ObjCInstanceMethodDecl
3783 : CXCursor_ObjCClassMethodDecl;
3784 case Decl::CXXMethod:
3785 return CXCursor_CXXMethod;
3786 case Decl::CXXConstructor:
3787 return CXCursor_Constructor;
3788 case Decl::CXXDestructor:
3789 return CXCursor_Destructor;
3790 case Decl::CXXConversion:
3791 return CXCursor_ConversionFunction;
3792 case Decl::ObjCProperty:
3793 return CXCursor_ObjCPropertyDecl;
3794 case Decl::ObjCProtocol:
3795 return CXCursor_ObjCProtocolDecl;
3796 case Decl::ParmVar:
3797 return CXCursor_ParmDecl;
3798 case Decl::Typedef:
3799 return CXCursor_TypedefDecl;
3800 case Decl::TypeAlias:
3801 return CXCursor_TypeAliasDecl;
3802 case Decl::TypeAliasTemplate:
3803 return CXCursor_TypeAliasTemplateDecl;
3804 case Decl::Var:
3805 return CXCursor_VarDecl;
3806 case Decl::Namespace:
3807 return CXCursor_Namespace;
3808 case Decl::NamespaceAlias:
3809 return CXCursor_NamespaceAlias;
3810 case Decl::TemplateTypeParm:
3811 return CXCursor_TemplateTypeParameter;
3812 case Decl::NonTypeTemplateParm:
3813 return CXCursor_NonTypeTemplateParameter;
3814 case Decl::TemplateTemplateParm:
3815 return CXCursor_TemplateTemplateParameter;
3816 case Decl::FunctionTemplate:
3817 return CXCursor_FunctionTemplate;
3818 case Decl::ClassTemplate:
3819 return CXCursor_ClassTemplate;
3820 case Decl::AccessSpec:
3821 return CXCursor_CXXAccessSpecifier;
3822 case Decl::ClassTemplatePartialSpecialization:
3823 return CXCursor_ClassTemplatePartialSpecialization;
3824 case Decl::UsingDirective:
3825 return CXCursor_UsingDirective;
3826 case Decl::StaticAssert:
3827 return CXCursor_StaticAssert;
3828 case Decl::Friend:
3829 return CXCursor_FriendDecl;
3830 case Decl::TranslationUnit:
3831 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003832
Fangrui Song050229d2018-11-24 00:14:31 +00003833 case Decl::Using:
3834 case Decl::UnresolvedUsingValue:
3835 case Decl::UnresolvedUsingTypename:
3836 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003837
Fangrui Song050229d2018-11-24 00:14:31 +00003838 case Decl::ObjCPropertyImpl:
3839 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3840 case ObjCPropertyImplDecl::Dynamic:
3841 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003842
Fangrui Song050229d2018-11-24 00:14:31 +00003843 case ObjCPropertyImplDecl::Synthesize:
3844 return CXCursor_ObjCSynthesizeDecl;
3845 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003846 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003847
3848 case Decl::Import:
3849 return CXCursor_ModuleImportDecl;
3850
3851 case Decl::ObjCTypeParam:
3852 return CXCursor_TemplateTypeParameter;
3853
3854 default:
3855 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3856 switch (TD->getTagKind()) {
3857 case TTK_Interface: // fall through
3858 case TTK_Struct:
3859 return CXCursor_StructDecl;
3860 case TTK_Class:
3861 return CXCursor_ClassDecl;
3862 case TTK_Union:
3863 return CXCursor_UnionDecl;
3864 case TTK_Enum:
3865 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003866 }
Fangrui Song050229d2018-11-24 00:14:31 +00003867 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003868 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003869
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003870 return CXCursor_UnexposedDecl;
3871}
3872
Douglas Gregor55b037b2010-07-08 20:55:51 +00003873static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003874 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003875 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003876 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003877
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003878 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003879
Eric Liu88de9f62018-09-19 09:34:55 +00003880 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3881 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003882 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003883 auto MD = PP.getMacroDefinition(M->first);
3884 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003885 MacroInfo *MI = MD.getMacroInfo();
3886 if (MI && MI->isUsedForHeaderGuard())
3887 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003888
Eric Liud485df12018-09-05 14:59:17 +00003889 Results.AddResult(
3890 Result(M->first, MI,
3891 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3892 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003893 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003894 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003895
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003896 Results.ExitScope();
3897}
3898
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003899static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003900 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003901 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003902
Douglas Gregorce0e8562010-08-23 21:54:33 +00003903 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003904
Douglas Gregorce0e8562010-08-23 21:54:33 +00003905 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3906 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003907 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003908 Results.AddResult(Result("__func__", CCP_Constant));
3909 Results.ExitScope();
3910}
3911
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003912static void HandleCodeCompleteResults(Sema *S,
3913 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003914 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003915 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003916 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003917 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003918 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003919}
3920
Ilya Biryukov41109672018-12-13 15:36:32 +00003921static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003922mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003923 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003924 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003925 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003926
John McCallfaf5fb42010-08-26 23:41:50 +00003927 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003928 return CodeCompletionContext::CCC_ClassStructUnion;
3929
John McCallfaf5fb42010-08-26 23:41:50 +00003930 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003931 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003932
John McCallfaf5fb42010-08-26 23:41:50 +00003933 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003934 return CodeCompletionContext::CCC_ObjCImplementation;
3935
John McCallfaf5fb42010-08-26 23:41:50 +00003936 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003937 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003938
John McCallfaf5fb42010-08-26 23:41:50 +00003939 case Sema::PCC_Template:
3940 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003941 if (S.CurContext->isFileContext())
3942 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003943 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003944 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003945 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003946
John McCallfaf5fb42010-08-26 23:41:50 +00003947 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003948 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003949
John McCallfaf5fb42010-08-26 23:41:50 +00003950 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003951 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003952 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003953 return CodeCompletionContext::CCC_ParenthesizedExpression;
3954 else
3955 return CodeCompletionContext::CCC_Expression;
3956
3957 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003958 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003959 case Sema::PCC_Condition:
3960 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3961 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003962
John McCallfaf5fb42010-08-26 23:41:50 +00003963 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003964 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003965
John McCallfaf5fb42010-08-26 23:41:50 +00003966 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003967 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003968
3969 case Sema::PCC_ParenthesizedExpression:
3970 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003971
Douglas Gregor80039242011-02-15 20:33:25 +00003972 case Sema::PCC_LocalDeclarationSpecifiers:
3973 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003974 }
David Blaikie8a40f702012-01-17 06:56:22 +00003975
3976 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003977}
3978
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003979/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003980/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003981/// overridden function as well as adding new functionality.
3982///
3983/// \param S The semantic analysis object for which we are generating results.
3984///
3985/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003986/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003987static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3988 ResultBuilder &Results) {
3989 // Look through blocks.
3990 DeclContext *CurContext = S.CurContext;
3991 while (isa<BlockDecl>(CurContext))
3992 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003993
Douglas Gregorac322ec2010-08-27 21:18:54 +00003994 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3995 if (!Method || !Method->isVirtual())
3996 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003997
3998 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003999 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00004000 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00004001 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00004002 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00004003
Douglas Gregor75acd922011-09-27 23:30:47 +00004004 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00004005 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004006 CodeCompletionBuilder Builder(Results.getAllocator(),
4007 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00004008 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
4009 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004010
Douglas Gregorac322ec2010-08-27 21:18:54 +00004011 // If we need a nested-name-specifier, add one now.
4012 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00004013 NestedNameSpecifier *NNS = getRequiredQualification(
4014 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00004015 if (NNS) {
4016 std::string Str;
4017 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00004018 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004019 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004020 }
4021 } else if (!InContext->Equals(Overridden->getDeclContext()))
4022 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004023
Fangrui Song050229d2018-11-24 00:14:31 +00004024 Builder.AddTypedTextChunk(
4025 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004026 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004027 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00004028 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00004029 if (FirstParam)
4030 FirstParam = false;
4031 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004032 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004033
Aaron Ballman43b68be2014-03-07 17:50:17 +00004034 Builder.AddPlaceholderChunk(
4035 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004036 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004037 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00004038 Results.AddResult(CodeCompletionResult(
4039 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
4040 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004041 Results.Ignore(Overridden);
4042 }
4043}
4044
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004045void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00004046 ModuleIdPath Path) {
4047 typedef CodeCompletionResult Result;
4048 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004049 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00004050 CodeCompletionContext::CCC_Other);
4051 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004052
Douglas Gregor07f43572012-01-29 18:15:03 +00004053 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004054 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00004055 typedef CodeCompletionResult Result;
4056 if (Path.empty()) {
4057 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00004058 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00004059 PP.getHeaderSearchInfo().collectAllModules(Modules);
4060 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
4061 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004062 Builder.getAllocator().CopyString(Modules[I]->Name));
4063 Results.AddResult(Result(
4064 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4065 Modules[I]->isAvailable() ? CXAvailability_Available
4066 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004067 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00004068 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00004069 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00004070 Module *Mod =
4071 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
4072 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00004073 // Enumerate submodules.
4074 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004075 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00004076 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00004077 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004078
Douglas Gregor07f43572012-01-29 18:15:03 +00004079 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004080 Builder.getAllocator().CopyString((*Sub)->Name));
4081 Results.AddResult(Result(
4082 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4083 (*Sub)->isAvailable() ? CXAvailability_Available
4084 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004085 }
4086 }
4087 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004088 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00004089 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004090 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00004091}
4092
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004093void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004094 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004095 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004096 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004097 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004098 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004099
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004100 // Determine how to filter results, e.g., so that the names of
4101 // values (functions, enumerators, function templates, etc.) are
4102 // only allowed where we can have an expression.
4103 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004104 case PCC_Namespace:
4105 case PCC_Class:
4106 case PCC_ObjCInterface:
4107 case PCC_ObjCImplementation:
4108 case PCC_ObjCInstanceVariableList:
4109 case PCC_Template:
4110 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004111 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004112 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004113 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4114 break;
4115
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004116 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00004117 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00004118 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004119 case PCC_ForInit:
4120 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00004121 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00004122 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4123 else
4124 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004125
David Blaikiebbafb8a2012-03-11 07:00:24 +00004126 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00004127 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004128 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004129
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004130 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00004131 // Unfiltered
4132 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004133 }
4134
Douglas Gregor9be0ed42010-08-26 16:36:48 +00004135 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004136 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00004137 auto ThisType = getCurrentThisType();
4138 if (!ThisType.isNull())
Sam McCall3dea5272019-06-10 15:17:52 +00004139 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(),
4140 VK_LValue);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004141
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004142 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004143 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004144 CodeCompleter->includeGlobals(),
4145 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00004146
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004147 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00004148 Results.ExitScope();
4149
Douglas Gregorce0e8562010-08-23 21:54:33 +00004150 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00004151 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004152 case PCC_Expression:
4153 case PCC_Statement:
4154 case PCC_RecoveryInFunction:
4155 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004156 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004157 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004158
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004159 case PCC_Namespace:
4160 case PCC_Class:
4161 case PCC_ObjCInterface:
4162 case PCC_ObjCImplementation:
4163 case PCC_ObjCInstanceVariableList:
4164 case PCC_Template:
4165 case PCC_MemberTemplate:
4166 case PCC_ForInit:
4167 case PCC_Condition:
4168 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004169 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004170 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00004171 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004172
Douglas Gregor9eb77012009-11-07 00:00:49 +00004173 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004174 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004175
Douglas Gregor50832e02010-09-20 22:39:41 +00004176 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004177 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00004178}
4179
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004180static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004181 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004182 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00004183 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004184 ResultBuilder &Results);
4185
4186void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
4187 bool AllowNonIdentifiers,
4188 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00004189 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004190 ResultBuilder Results(
4191 *this, CodeCompleter->getAllocator(),
4192 CodeCompleter->getCodeCompletionTUInfo(),
4193 AllowNestedNameSpecifiers
4194 // FIXME: Try to separate codepath leading here to deduce whether we
4195 // need an existing symbol or a new one.
4196 ? CodeCompletionContext::CCC_SymbolOrNewName
4197 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004198 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004199
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004200 // Type qualifiers can come after names.
4201 Results.AddResult(Result("const"));
4202 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004203 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004204 Results.AddResult(Result("restrict"));
4205
David Blaikiebbafb8a2012-03-11 07:00:24 +00004206 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004207 if (getLangOpts().CPlusPlus11 &&
4208 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4209 DS.getTypeSpecType() == DeclSpec::TST_struct))
4210 Results.AddResult("final");
4211
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004212 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004213 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004214 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004215
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004216 // Add nested-name-specifiers.
4217 if (AllowNestedNameSpecifiers) {
4218 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004219 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004220 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4221 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004222 CodeCompleter->includeGlobals(),
4223 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004224 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004225 }
4226 }
4227 Results.ExitScope();
4228
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004229 // If we're in a context where we might have an expression (rather than a
4230 // declaration), and what we've seen so far is an Objective-C type that could
4231 // be a receiver of a class message, this may be a class message send with
4232 // the initial opening bracket '[' missing. Add appropriate completions.
4233 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004234 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004235 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004236 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4237 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004238 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004239 (S->getFlags() & Scope::DeclScope) != 0 &&
4240 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004241 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4242 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004243 ParsedType T = DS.getRepAsType();
4244 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004245 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004246 }
4247
Douglas Gregor56ccce02010-08-24 04:59:56 +00004248 // Note that we intentionally suppress macro results here, since we do not
4249 // encourage using macros to produce the names of entities.
4250
Fangrui Song050229d2018-11-24 00:14:31 +00004251 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004252 Results.data(), Results.size());
4253}
4254
Douglas Gregor68762e72010-08-23 21:17:50 +00004255struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004256 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4257 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004258 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004259 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004260
Douglas Gregor68762e72010-08-23 21:17:50 +00004261 QualType PreferredType;
4262 bool IntegralConstantExpression;
4263 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004264 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004265 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004266};
4267
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004268namespace {
4269/// Information that allows to avoid completing redundant enumerators.
4270struct CoveredEnumerators {
4271 llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
4272 NestedNameSpecifier *SuggestedQualifier = nullptr;
4273};
4274} // namespace
4275
4276static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
4277 EnumDecl *Enum, DeclContext *CurContext,
4278 const CoveredEnumerators &Enumerators) {
4279 NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
4280 if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
4281 // If there are no prior enumerators in C++, check whether we have to
4282 // qualify the names of the enumerators that we suggest, because they
4283 // may not be visible in this scope.
4284 Qualifier = getRequiredQualification(Context, CurContext, Enum);
4285 }
4286
4287 Results.EnterNewScope();
4288 for (auto *E : Enum->enumerators()) {
4289 if (Enumerators.Seen.count(E))
4290 continue;
4291
4292 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
4293 Results.AddResult(R, CurContext, nullptr, false);
4294 }
4295 Results.ExitScope();
4296}
4297
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004298/// Try to find a corresponding FunctionProtoType for function-like types (e.g.
4299/// function pointers, std::function, etc).
4300static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) {
4301 assert(!T.isNull());
4302 // Try to extract first template argument from std::function<> and similar.
4303 // Note we only handle the sugared types, they closely match what users wrote.
4304 // We explicitly choose to not handle ClassTemplateSpecializationDecl.
4305 if (auto *Specialization = T->getAs<TemplateSpecializationType>()) {
4306 if (Specialization->getNumArgs() != 1)
4307 return nullptr;
4308 const TemplateArgument &Argument = Specialization->getArg(0);
4309 if (Argument.getKind() != TemplateArgument::Type)
4310 return nullptr;
4311 return Argument.getAsType()->getAs<FunctionProtoType>();
4312 }
4313 // Handle other cases.
4314 if (T->isPointerType())
4315 T = T->getPointeeType();
4316 return T->getAs<FunctionProtoType>();
4317}
4318
4319/// Adds a pattern completion for a lambda expression with the specified
4320/// parameter types and placeholders for parameter names.
4321static void AddLambdaCompletion(ResultBuilder &Results,
4322 llvm::ArrayRef<QualType> Parameters,
4323 const LangOptions &LangOpts) {
Ilya Biryukovfd11a5f2019-05-23 16:39:26 +00004324 if (!Results.includeCodePatterns())
4325 return;
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004326 CodeCompletionBuilder Completion(Results.getAllocator(),
4327 Results.getCodeCompletionTUInfo());
4328 // [](<parameters>) {}
4329 Completion.AddChunk(CodeCompletionString::CK_LeftBracket);
4330 Completion.AddPlaceholderChunk("=");
4331 Completion.AddChunk(CodeCompletionString::CK_RightBracket);
4332 if (!Parameters.empty()) {
4333 Completion.AddChunk(CodeCompletionString::CK_LeftParen);
4334 bool First = true;
4335 for (auto Parameter : Parameters) {
4336 if (!First)
4337 Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma);
4338 else
4339 First = false;
4340
4341 constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!";
Benjamin Krameradcd0262020-01-28 20:23:46 +01004342 std::string Type = std::string(NamePlaceholder);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004343 Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts));
4344 llvm::StringRef Prefix, Suffix;
4345 std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder);
4346 Prefix = Prefix.rtrim();
4347 Suffix = Suffix.ltrim();
4348
4349 Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix));
4350 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4351 Completion.AddPlaceholderChunk("parameter");
4352 Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix));
4353 };
4354 Completion.AddChunk(CodeCompletionString::CK_RightParen);
4355 }
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004356 Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004357 Completion.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004358 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004359 Completion.AddPlaceholderChunk("body");
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004360 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004361 Completion.AddChunk(CodeCompletionString::CK_RightBrace);
4362
4363 Results.AddResult(Completion.TakeString());
4364}
4365
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004366/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004367/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004368void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004369 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004370 ResultBuilder Results(
4371 *this, CodeCompleter->getAllocator(),
4372 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004373 CodeCompletionContext(
4374 Data.IsParenthesized
4375 ? CodeCompletionContext::CCC_ParenthesizedExpression
4376 : CodeCompletionContext::CCC_Expression,
4377 Data.PreferredType));
4378 auto PCC =
4379 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004380 if (Data.ObjCCollection)
4381 Results.setFilter(&ResultBuilder::IsObjCCollection);
4382 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004383 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004384 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004385 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4386 else
4387 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004388
4389 if (!Data.PreferredType.isNull())
4390 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004391
Douglas Gregor68762e72010-08-23 21:17:50 +00004392 // Ignore any declarations that we were told that we don't care about.
4393 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4394 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004395
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004396 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004397 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004398 CodeCompleter->includeGlobals(),
4399 CodeCompleter->loadExternal());
4400
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004401 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004402 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004403 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004404
Douglas Gregor55b037b2010-07-08 20:55:51 +00004405 bool PreferredTypeIsPointer = false;
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004406 if (!Data.PreferredType.isNull()) {
Fangrui Song050229d2018-11-24 00:14:31 +00004407 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4408 Data.PreferredType->isMemberPointerType() ||
4409 Data.PreferredType->isBlockPointerType();
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004410 if (Data.PreferredType->isEnumeralType()) {
4411 EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();
4412 if (auto *Def = Enum->getDefinition())
4413 Enum = Def;
4414 // FIXME: collect covered enumerators in cases like:
4415 // if (x == my_enum::one) { ... } else if (x == ^) {}
4416 AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators());
4417 }
4418 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004419
Fangrui Song050229d2018-11-24 00:14:31 +00004420 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004421 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004422 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004423
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004424 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004425 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4426 PreferredTypeIsPointer);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004427
4428 // Complete a lambda expression when preferred type is a function.
4429 if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) {
4430 if (const FunctionProtoType *F =
4431 TryDeconstructFunctionLike(Data.PreferredType))
4432 AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts());
4433 }
4434
Eric Liuf5ba09f2018-07-04 10:01:18 +00004435 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4436 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004437}
4438
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004439void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4440 bool IsParenthesized) {
4441 return CodeCompleteExpression(
4442 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004443}
4444
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004445void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4446 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004447 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004448 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004449 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004450 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004451}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004452
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004453/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004454/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004455typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004456
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004457/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004458static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4459 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4460 if (Interface->hasDefinition())
4461 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004462
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004463 return Interface;
4464 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004465
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004466 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4467 if (Protocol->hasDefinition())
4468 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004469
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004470 return Protocol;
4471 }
4472 return Container;
4473}
4474
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004475/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004476/// declaration \p BD.
4477static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4478 CodeCompletionBuilder &Builder,
4479 const NamedDecl *BD,
4480 const FunctionTypeLoc &BlockLoc,
4481 const FunctionProtoTypeLoc &BlockProtoLoc) {
4482 Builder.AddResultTypeChunk(
4483 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4484 Policy, Builder.getAllocator()));
4485
4486 AddTypedNameChunk(Context, Policy, BD, Builder);
4487 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4488
4489 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4490 Builder.AddPlaceholderChunk("...");
4491 } else {
4492 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4493 if (I)
4494 Builder.AddChunk(CodeCompletionString::CK_Comma);
4495
4496 // Format the placeholder string.
4497 std::string PlaceholderStr =
4498 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4499
4500 if (I == N - 1 && BlockProtoLoc &&
4501 BlockProtoLoc.getTypePtr()->isVariadic())
4502 PlaceholderStr += ", ...";
4503
4504 // Add the placeholder string.
4505 Builder.AddPlaceholderChunk(
4506 Builder.getAllocator().CopyString(PlaceholderStr));
4507 }
4508 }
4509
4510 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4511}
4512
Fangrui Song050229d2018-11-24 00:14:31 +00004513static void
4514AddObjCProperties(const CodeCompletionContext &CCContext,
4515 ObjCContainerDecl *Container, bool AllowCategories,
4516 bool AllowNullaryMethods, DeclContext *CurContext,
4517 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4518 bool IsBaseExprStatement = false,
4519 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004520 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004521
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004522 // Retrieve the definition.
4523 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004524
Douglas Gregor9291bad2009-11-18 01:29:26 +00004525 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004526 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004527 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004528 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004529
Alex Lorenzbaef8022016-11-09 13:43:18 +00004530 // FIXME: Provide block invocation completion for non-statement
4531 // expressions.
4532 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4533 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004534 Result R = Result(P, Results.getBasePriority(P), nullptr);
4535 if (!InOriginalClass)
4536 setInBaseClass(R);
4537 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004538 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004539 }
4540
4541 // Block setter and invocation completion is provided only when we are able
4542 // to find the FunctionProtoTypeLoc with parameter names for the block.
4543 FunctionTypeLoc BlockLoc;
4544 FunctionProtoTypeLoc BlockProtoLoc;
4545 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4546 BlockProtoLoc);
4547 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004548 Result R = Result(P, Results.getBasePriority(P), nullptr);
4549 if (!InOriginalClass)
4550 setInBaseClass(R);
4551 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004552 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004553 }
4554
4555 // The default completion result for block properties should be the block
4556 // invocation completion when the base expression is a statement.
4557 CodeCompletionBuilder Builder(Results.getAllocator(),
4558 Results.getCodeCompletionTUInfo());
4559 AddObjCBlockCall(Container->getASTContext(),
4560 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4561 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004562 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4563 if (!InOriginalClass)
4564 setInBaseClass(R);
4565 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004566
4567 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004568 // statement and the block property is mutable.
4569 if (!P->isReadOnly()) {
4570 CodeCompletionBuilder Builder(Results.getAllocator(),
4571 Results.getCodeCompletionTUInfo());
4572 AddResultTypeChunk(Container->getASTContext(),
4573 getCompletionPrintingPolicy(Results.getSema()), P,
4574 CCContext.getBaseType(), Builder);
4575 Builder.AddTypedTextChunk(
4576 Results.getAllocator().CopyString(P->getName()));
4577 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004578
Alex Lorenzbaef8022016-11-09 13:43:18 +00004579 std::string PlaceholderStr = formatBlockPlaceholder(
4580 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4581 BlockProtoLoc, /*SuppressBlockName=*/true);
4582 // Add the placeholder string.
4583 Builder.AddPlaceholderChunk(
4584 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004585
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004586 // When completing blocks properties that return void the default
4587 // property completion result should show up before the setter,
4588 // otherwise the setter completion should show up before the default
4589 // property completion, as we normally want to use the result of the
4590 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004591 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004592 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004593 Results.getBasePriority(P) +
4594 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4595 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004596 : -CCD_BlockPropertySetter));
4597 if (!InOriginalClass)
4598 setInBaseClass(R);
4599 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004600 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004601 };
4602
4603 if (IsClassProperty) {
4604 for (const auto *P : Container->class_properties())
4605 AddProperty(P);
4606 } else {
4607 for (const auto *P : Container->instance_properties())
4608 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004609 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004610
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004611 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004612 if (AllowNullaryMethods) {
4613 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004614 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004615 // Adds a method result
4616 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4617 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4618 if (!Name)
4619 return;
4620 if (!AddedProperties.insert(Name).second)
4621 return;
4622 CodeCompletionBuilder Builder(Results.getAllocator(),
4623 Results.getCodeCompletionTUInfo());
4624 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4625 Builder.AddTypedTextChunk(
4626 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004627 Result R = Result(Builder.TakeString(), M,
4628 CCP_MemberDeclaration + CCD_MethodAsProperty);
4629 if (!InOriginalClass)
4630 setInBaseClass(R);
4631 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004632 };
4633
4634 if (IsClassProperty) {
4635 for (const auto *M : Container->methods()) {
4636 // Gather the class method that can be used as implicit property
4637 // getters. Methods with arguments or methods that return void aren't
4638 // added to the results as they can't be used as a getter.
4639 if (!M->getSelector().isUnarySelector() ||
4640 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4641 continue;
4642 AddMethod(M);
4643 }
4644 } else {
4645 for (auto *M : Container->methods()) {
4646 if (M->getSelector().isUnarySelector())
4647 AddMethod(M);
4648 }
Douglas Gregor95147142011-05-05 15:50:42 +00004649 }
4650 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004651
Douglas Gregor9291bad2009-11-18 01:29:26 +00004652 // Add properties in referenced protocols.
4653 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004654 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004655 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004656 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004657 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004658 /*InOriginalClass*/ false);
4659 } else if (ObjCInterfaceDecl *IFace =
4660 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004661 if (AllowCategories) {
4662 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004663 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004664 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004665 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004666 IsBaseExprStatement, IsClassProperty,
4667 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004668 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004669
Douglas Gregor9291bad2009-11-18 01:29:26 +00004670 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004671 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004672 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004673 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004674 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004675 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004676
Douglas Gregor9291bad2009-11-18 01:29:26 +00004677 // Look in the superclass.
4678 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004679 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004680 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004681 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004682 /*InOriginalClass*/ false);
4683 } else if (const auto *Category =
4684 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004685 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004686 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004687 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004688 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004689 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004690 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004691 }
4692}
4693
Sam McCall3dea5272019-06-10 15:17:52 +00004694static void AddRecordMembersCompletionResults(
4695 Sema &SemaRef, ResultBuilder &Results, Scope *S, QualType BaseType,
4696 ExprValueKind BaseKind, RecordDecl *RD, Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004697 // Indicate that we are performing a member access, and the cv-qualifiers
4698 // for the base object type.
Sam McCall3dea5272019-06-10 15:17:52 +00004699 Results.setObjectTypeQualifiers(BaseType.getQualifiers(), BaseKind);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004700
4701 // Access to a C/C++ class, struct, or union.
4702 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004703 std::vector<FixItHint> FixIts;
4704 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004705 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004706 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004707 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004708 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004709 /*IncludeDependentBases=*/true,
4710 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004711
4712 if (SemaRef.getLangOpts().CPlusPlus) {
4713 if (!Results.empty()) {
4714 // The "template" keyword can follow "->" or "." in the grammar.
4715 // However, we only want to suggest the template keyword if something
4716 // is dependent.
4717 bool IsDependent = BaseType->isDependentType();
4718 if (!IsDependent) {
4719 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4720 if (DeclContext *Ctx = DepScope->getEntity()) {
4721 IsDependent = Ctx->isDependentContext();
4722 break;
4723 }
4724 }
4725
4726 if (IsDependent)
4727 Results.AddResult(CodeCompletionResult("template"));
4728 }
4729 }
4730}
4731
Kadir Cetinkaya42e94782020-01-23 13:28:16 +01004732// Returns the RecordDecl inside the BaseType, falling back to primary template
4733// in case of specializations. Since we might not have a decl for the
4734// instantiation/specialization yet, e.g. dependent code.
4735static RecordDecl *getAsRecordDecl(const QualType BaseType) {
4736 if (auto *RD = BaseType->getAsRecordDecl())
4737 return RD;
4738
4739 if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
4740 if (const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(
4741 TST->getTemplateName().getAsTemplateDecl())) {
4742 return TD->getTemplatedDecl();
4743 }
4744 }
4745
4746 return nullptr;
4747}
4748
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004749void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004750 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004751 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004752 bool IsBaseExprStatement,
4753 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004754 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004755 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004756
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004757 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4758 if (ConvertedBase.isInvalid())
4759 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004760 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4761
4762 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004763
4764 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004765 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004766 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004767 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004768
Douglas Gregor21325842011-07-07 16:03:39 +00004769 if (IsArrow) {
4770 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004771 } else {
4772 if (ConvertedBaseType->isObjCObjectPointerType() ||
4773 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004774 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004775 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004776 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4777 }
4778 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004779
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004780 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004781 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004782 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004783 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004784 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004785
Fangrui Song050229d2018-11-24 00:14:31 +00004786 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4787 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004788 if (!Base)
4789 return false;
4790
4791 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4792 if (ConvertedBase.isInvalid())
4793 return false;
4794 Base = ConvertedBase.get();
4795
4796 QualType BaseType = Base->getType();
Kadir Cetinkaya42e94782020-01-23 13:28:16 +01004797 if (BaseType.isNull())
4798 return false;
Sam McCall3dea5272019-06-10 15:17:52 +00004799 ExprValueKind BaseKind = Base->getValueKind();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004800
4801 if (IsArrow) {
Sam McCall3dea5272019-06-10 15:17:52 +00004802 if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004803 BaseType = Ptr->getPointeeType();
Sam McCall3dea5272019-06-10 15:17:52 +00004804 BaseKind = VK_LValue;
4805 } else if (BaseType->isObjCObjectPointerType())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004806 /*Do nothing*/;
4807 else
4808 return false;
4809 }
4810
Kadir Cetinkaya42e94782020-01-23 13:28:16 +01004811 if (RecordDecl *RD = getAsRecordDecl(BaseType)) {
Sam McCall3dea5272019-06-10 15:17:52 +00004812 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
Kadir Cetinkaya42e94782020-01-23 13:28:16 +01004813 RD, std::move(AccessOpFixIt));
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004814 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4815 // Objective-C property reference.
4816 AddedPropertiesSet AddedProperties;
4817
4818 if (const ObjCObjectPointerType *ObjCPtr =
4819 BaseType->getAsObjCInterfacePointerType()) {
4820 // Add property results based on our interface.
4821 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4822 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4823 /*AllowNullaryMethods=*/true, CurContext,
4824 AddedProperties, Results, IsBaseExprStatement);
4825 }
4826
4827 // Add properties from the protocols in a qualified interface.
Simon Pilgrimbf039442020-01-11 16:01:46 +00004828 for (auto *I : BaseType->castAs<ObjCObjectPointerType>()->quals())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004829 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4830 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004831 IsBaseExprStatement, /*IsClassProperty*/ false,
4832 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004833 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4834 (!IsArrow && BaseType->isObjCObjectType())) {
4835 // Objective-C instance variable access.
4836 ObjCInterfaceDecl *Class = nullptr;
4837 if (const ObjCObjectPointerType *ObjCPtr =
4838 BaseType->getAs<ObjCObjectPointerType>())
4839 Class = ObjCPtr->getInterfaceDecl();
4840 else
Simon Pilgrimbf039442020-01-11 16:01:46 +00004841 Class = BaseType->castAs<ObjCObjectType>()->getInterface();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004842
4843 // Add all ivars from this class and its superclasses.
4844 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004845 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004846 Results.setFilter(&ResultBuilder::IsObjCIvar);
4847 LookupVisibleDecls(
4848 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4849 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4850 }
4851 }
4852
4853 // FIXME: How do we cope with isa?
4854 return true;
4855 };
4856
Douglas Gregor9291bad2009-11-18 01:29:26 +00004857 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004858
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004859 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4860 if (CodeCompleter->includeFixIts()) {
4861 const CharSourceRange OpRange =
4862 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4863 CompletionSucceded |= DoCompletion(
4864 OtherOpBase, !IsArrow,
4865 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004866 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004867
Douglas Gregor9291bad2009-11-18 01:29:26 +00004868 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004869
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004870 if (!CompletionSucceded)
4871 return;
4872
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004873 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004874 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4875 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004876}
4877
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004878void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4879 IdentifierInfo &ClassName,
4880 SourceLocation ClassNameLoc,
4881 bool IsBaseExprStatement) {
4882 IdentifierInfo *ClassNamePtr = &ClassName;
4883 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4884 if (!IFace)
4885 return;
4886 CodeCompletionContext CCContext(
4887 CodeCompletionContext::CCC_ObjCPropertyAccess);
4888 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4889 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4890 &ResultBuilder::IsMember);
4891 Results.EnterNewScope();
4892 AddedPropertiesSet AddedProperties;
4893 AddObjCProperties(CCContext, IFace, true,
4894 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4895 Results, IsBaseExprStatement,
4896 /*IsClassProperty=*/true);
4897 Results.ExitScope();
4898 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4899 Results.data(), Results.size());
4900}
4901
Faisal Vali090da2d2018-01-01 18:23:28 +00004902void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004903 if (!CodeCompleter)
4904 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004905
4906 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004907 enum CodeCompletionContext::Kind ContextKind =
4908 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004909 switch ((DeclSpec::TST)TagSpec) {
4910 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004911 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004912 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004913 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004914
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004915 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004916 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004917 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004918 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004919
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004920 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004921 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004922 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004923 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004924 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004925 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004926
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004927 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004928 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004929 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004930
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004931 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4932 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004933 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004934
4935 // First pass: look for tags.
4936 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004937 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004938 CodeCompleter->includeGlobals(),
4939 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004940
Douglas Gregor39982192010-08-15 06:18:01 +00004941 if (CodeCompleter->includeGlobals()) {
4942 // Second pass: look for nested name specifiers.
4943 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004944 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4945 CodeCompleter->includeGlobals(),
4946 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004947 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004948
Douglas Gregor0ac41382010-09-23 23:01:17 +00004949 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004950 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004951}
4952
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004953static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4954 const LangOptions &LangOpts) {
4955 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4956 Results.AddResult("const");
4957 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4958 Results.AddResult("volatile");
4959 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4960 Results.AddResult("restrict");
4961 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4962 Results.AddResult("_Atomic");
4963 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4964 Results.AddResult("__unaligned");
4965}
4966
Douglas Gregor28c78432010-08-27 17:35:51 +00004967void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004968 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004969 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004970 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004971 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004972 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004973 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004974 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004975 Results.data(), Results.size());
4976}
4977
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004978void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4979 const VirtSpecifiers *VS) {
4980 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4981 CodeCompleter->getCodeCompletionTUInfo(),
4982 CodeCompletionContext::CCC_TypeQualifiers);
4983 Results.EnterNewScope();
4984 AddTypeQualifierResults(DS, Results, LangOpts);
4985 if (LangOpts.CPlusPlus11) {
4986 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004987 if (D.getContext() == DeclaratorContext::MemberContext &&
4988 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004989 if (!VS || !VS->isFinalSpecified())
4990 Results.AddResult("final");
4991 if (!VS || !VS->isOverrideSpecified())
4992 Results.AddResult("override");
4993 }
4994 }
4995 Results.ExitScope();
4996 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4997 Results.data(), Results.size());
4998}
4999
Benjamin Kramer72dae622016-02-18 15:30:24 +00005000void Sema::CodeCompleteBracketDeclarator(Scope *S) {
5001 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
5002}
5003
Douglas Gregord328d572009-09-21 18:10:23 +00005004void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00005005 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00005006 return;
John McCall5939b162011-08-06 07:30:58 +00005007
Richard Smithef6c43d2018-07-26 18:41:30 +00005008 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00005009 // Condition expression might be invalid, do not continue in this case.
5010 if (!Switch->getCond())
5011 return;
John McCall5939b162011-08-06 07:30:58 +00005012 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
5013 if (!type->isEnumeralType()) {
5014 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00005015 Data.IntegralConstantExpression = true;
5016 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00005017 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00005018 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005019
Douglas Gregord328d572009-09-21 18:10:23 +00005020 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005021 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00005022 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005023 if (EnumDecl *Def = Enum->getDefinition())
5024 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005025
Douglas Gregord328d572009-09-21 18:10:23 +00005026 // Determine which enumerators we have already seen in the switch statement.
5027 // FIXME: Ideally, we would also be able to look *past* the code-completion
5028 // token, in case we are code-completing in the middle of the switch and not
5029 // at the end. However, we aren't able to do so at the moment.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005030 CoveredEnumerators Enumerators;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005031 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00005032 SC = SC->getNextSwitchCase()) {
5033 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
5034 if (!Case)
5035 continue;
5036
5037 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00005038 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
5039 if (auto *Enumerator =
5040 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005041 // We look into the AST of the case statement to determine which
5042 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00005043 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005044 // values of each enumerator. However, value-based approach would not
5045 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00005046 // template are type- and value-dependent.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005047 Enumerators.Seen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005048
Douglas Gregorf2510672009-09-21 19:57:38 +00005049 // If this is a qualified-id, keep track of the nested-name-specifier
5050 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00005051 //
5052 // switch (TagD.getKind()) {
5053 // case TagDecl::TK_enum:
5054 // break;
5055 // case XXX
5056 //
Douglas Gregorf2510672009-09-21 19:57:38 +00005057 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00005058 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
5059 // TK_struct, and TK_class.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005060 Enumerators.SuggestedQualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00005061 }
5062 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005063
Douglas Gregord328d572009-09-21 18:10:23 +00005064 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005065 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005066 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005067 CodeCompletionContext::CCC_Expression);
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005068 AddEnumerators(Results, Context, Enum, CurContext, Enumerators);
Douglas Gregor285560922010-04-06 20:02:15 +00005069
Douglas Gregor21325842011-07-07 16:03:39 +00005070 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00005071 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00005072 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00005073 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5074 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00005075}
5076
Robert Wilhelm16e94b92013-08-09 18:02:13 +00005077static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005078 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005079 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005080
5081 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005082 if (!Args[I])
5083 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005084
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005085 return false;
5086}
5087
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005088typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
5089
Fangrui Song050229d2018-11-24 00:14:31 +00005090static void mergeCandidatesWithResults(
5091 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
5092 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Fangrui Song899d1392019-04-24 14:43:05 +00005093 // Sort the overload candidate set by placing the best overloads first.
5094 llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
5095 const OverloadCandidate &Y) {
5096 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
5097 CandidateSet.getKind());
5098 });
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005099
Fangrui Song899d1392019-04-24 14:43:05 +00005100 // Add the remaining viable overload candidates as code-completion results.
5101 for (OverloadCandidate &Candidate : CandidateSet) {
5102 if (Candidate.Function && Candidate.Function->isDeleted())
5103 continue;
5104 if (Candidate.Viable)
5105 Results.push_back(ResultCandidate(Candidate.Function));
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005106 }
5107}
5108
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005109/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005110/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00005111static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00005112 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005113
5114 // Given the overloads 'Candidates' for a function call matching all arguments
5115 // up to N, return the type of the Nth parameter if it is the same for all
5116 // overload candidates.
5117 QualType ParamType;
5118 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00005119 if (const auto *FType = Candidate.getFunctionType())
5120 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005121 if (N < Proto->getNumParams()) {
5122 if (ParamType.isNull())
5123 ParamType = Proto->getParamType(N);
5124 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00005125 ParamType.getNonReferenceType(),
5126 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005127 // Otherwise return a default-constructed QualType.
5128 return QualType();
5129 }
5130 }
5131
5132 return ParamType;
5133}
5134
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005135static QualType
5136ProduceSignatureHelp(Sema &SemaRef, Scope *S,
5137 MutableArrayRef<ResultCandidate> Candidates,
5138 unsigned CurrentArg, SourceLocation OpenParLoc) {
5139 if (Candidates.empty())
5140 return QualType();
5141 SemaRef.CodeCompleter->ProcessOverloadCandidates(
5142 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
5143 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005144}
5145
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005146QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
5147 ArrayRef<Expr *> Args,
5148 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00005149 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005150 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005151
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005152 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00005153 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005154 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
5155 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005156 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005157 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005158
John McCall57500772009-12-16 12:17:52 +00005159 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00005160 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00005161 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00005162
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005163 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00005164
John McCall57500772009-12-16 12:17:52 +00005165 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005166 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005167 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005168 /*PartialOverloading=*/true);
5169 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
5170 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
5171 if (UME->hasExplicitTemplateArgs()) {
5172 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
5173 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00005174 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00005175
5176 // Add the base as first argument (use a nullptr if the base is implicit).
5177 SmallVector<Expr *, 12> ArgExprs(
5178 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005179 ArgExprs.append(Args.begin(), Args.end());
5180 UnresolvedSet<8> Decls;
5181 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00005182 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005183 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005184 /*SuppressUserConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00005185 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005186 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005187 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00005188 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005189 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00005190 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005191 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005192 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00005193 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005194 !FD->getType()->getAs<FunctionProtoType>())
5195 Results.push_back(ResultCandidate(FD));
5196 else
5197 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
5198 Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005199 /*SuppressUserConversions=*/false,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005200 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005201
5202 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
5203 // If expression's type is CXXRecordDecl, it may overload the function
5204 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005205 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00005206 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00005207 DeclarationName OpName =
5208 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005209 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
5210 LookupQualifiedName(R, DC);
5211 R.suppressDiagnostics();
5212 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
5213 ArgExprs.append(Args.begin(), Args.end());
5214 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
5215 /*ExplicitArgs=*/nullptr,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005216 /*SuppressUserConversions=*/false,
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005217 /*PartialOverloading=*/true);
5218 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005219 } else {
5220 // Lastly we check whether expression's type is function pointer or
5221 // function.
5222 QualType T = NakedFn->getType();
5223 if (!T->getPointeeType().isNull())
5224 T = T->getPointeeType();
5225
5226 if (auto FP = T->getAs<FunctionProtoType>()) {
5227 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00005228 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005229 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005230 Results.push_back(ResultCandidate(FP));
5231 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005232 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005233 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005234 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005235 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005236 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005237 QualType ParamType =
5238 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
5239 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005240}
5241
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005242QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
5243 SourceLocation Loc,
5244 ArrayRef<Expr *> Args,
5245 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005246 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005247 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005248
5249 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00005250 CXXRecordDecl *RD =
5251 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005252 if (!RD)
5253 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00005254
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005255 // FIXME: Provide support for member initializers.
5256 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005257
5258 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
5259
Fangrui Song050229d2018-11-24 00:14:31 +00005260 for (NamedDecl *C : LookupConstructors(RD)) {
5261 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
5262 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
5263 CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005264 /*SuppressUserConversions=*/false,
Richard Smith76b90272019-05-09 03:59:21 +00005265 /*PartialOverloading=*/true,
5266 /*AllowExplicit*/ true);
Fangrui Song050229d2018-11-24 00:14:31 +00005267 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
5268 AddTemplateOverloadCandidate(
5269 FTD, DeclAccessPair::make(FTD, C->getAccess()),
5270 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005271 /*SuppressUserConversions=*/false,
Hans Wennborgd2b9fc82019-05-06 09:51:10 +00005272 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005273 }
5274 }
5275
5276 SmallVector<ResultCandidate, 8> Results;
5277 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005278 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00005279}
5280
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00005281QualType Sema::ProduceCtorInitMemberSignatureHelp(
5282 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
5283 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
5284 if (!CodeCompleter)
5285 return QualType();
5286
5287 CXXConstructorDecl *Constructor =
5288 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
5289 if (!Constructor)
5290 return QualType();
5291 // FIXME: Add support for Base class constructors as well.
5292 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
5293 Constructor->getParent(), SS, TemplateTypeTy, II))
5294 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
5295 MemberDecl->getLocation(), ArgExprs,
5296 OpenParLoc);
5297 return QualType();
5298}
5299
Kadir Cetinkaya42e94782020-01-23 13:28:16 +01005300void Sema::CodeCompleteDesignator(const QualType BaseType,
5301 llvm::ArrayRef<Expr *> InitExprs,
5302 const Designation &D) {
5303 if (BaseType.isNull())
5304 return;
5305 // FIXME: Handle nested designations, e.g. : .x.^
5306 if (!D.empty())
5307 return;
5308
5309 const auto *RD = getAsRecordDecl(BaseType);
5310 if (!RD)
5311 return;
5312 if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
5313 // Template might not be instantiated yet, fall back to primary template in
5314 // such cases.
5315 if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared)
5316 RD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
5317 }
5318 if (RD->fields().empty())
5319 return;
5320
5321 CodeCompletionContext CCC(CodeCompletionContext::CCC_DotMemberAccess,
5322 BaseType);
5323 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5324 CodeCompleter->getCodeCompletionTUInfo(), CCC);
5325
5326 Results.EnterNewScope();
5327 for (const auto *FD : RD->fields()) {
5328 // FIXME: Make use of previous designators to mark any fields before those
5329 // inaccessible, and also compute the next initializer priority.
5330 ResultBuilder::Result Result(FD, Results.getBasePriority(FD));
5331 Results.AddResult(Result, CurContext, /*Hiding=*/nullptr);
5332 }
5333 Results.ExitScope();
5334 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5335 Results.data(), Results.size());
5336}
5337
John McCall48871652010-08-21 09:40:31 +00005338void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
5339 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005340 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005341 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005342 return;
5343 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005344
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005345 CodeCompleteExpressionData Data;
5346 Data.PreferredType = VD->getType();
5347 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5348 Data.IgnoreDecls.push_back(VD);
5349
5350 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005351}
5352
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005353void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005354 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005355 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005356 mapCodeCompletionContext(*this, PCC_Statement));
5357 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5358 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005359
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005360 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5361 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005362 CodeCompleter->includeGlobals(),
5363 CodeCompleter->loadExternal());
5364
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005365 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005366
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005367 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005368 CodeCompletionBuilder Builder(Results.getAllocator(),
5369 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005370 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005371 if (Results.includeCodePatterns()) {
5372 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5373 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5374 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5375 Builder.AddPlaceholderChunk("statements");
5376 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5377 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5378 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005379 Results.AddResult(Builder.TakeString());
5380
5381 // "else if" block
Ilya Biryukov30977fc2019-06-04 09:26:08 +00005382 Builder.AddTypedTextChunk("else if");
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005383 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5384 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005385 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005386 Builder.AddPlaceholderChunk("condition");
5387 else
5388 Builder.AddPlaceholderChunk("expression");
5389 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005390 if (Results.includeCodePatterns()) {
5391 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5392 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5393 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5394 Builder.AddPlaceholderChunk("statements");
5395 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5396 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5397 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005398 Results.AddResult(Builder.TakeString());
5399
5400 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005401
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005402 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005403 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005404
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005405 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005406 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005407
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005408 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005409 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005410}
5411
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005412void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005413 bool EnteringContext,
5414 bool IsUsingDeclaration, QualType BaseType,
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005415 QualType PreferredType) {
Eric Liu06d34022017-12-12 11:35:46 +00005416 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005417 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005418
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005419 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType);
5420 CC.setIsUsingDeclaration(IsUsingDeclaration);
5421 CC.setCXXScopeSpecifier(SS);
5422
Eric Liu06d34022017-12-12 11:35:46 +00005423 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5424 // "a::b::" is not corresponding to any context/namespace in the AST), since
5425 // it can be useful for global code completion which have information about
5426 // contexts/symbols that are not in the AST.
5427 if (SS.isInvalid()) {
Eric Liu206740e2019-02-21 11:22:58 +00005428 // As SS is invalid, we try to collect accessible contexts from the current
5429 // scope with a dummy lookup so that the completion consumer can try to
5430 // guess what the specified scope is.
5431 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5432 CodeCompleter->getCodeCompletionTUInfo(), CC);
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005433 if (!PreferredType.isNull())
5434 DummyResults.setPreferredType(PreferredType);
Eric Liu206740e2019-02-21 11:22:58 +00005435 if (S->getEntity()) {
5436 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5437 BaseType);
5438 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5439 /*IncludeGlobalScope=*/false,
5440 /*LoadExternal=*/false);
5441 }
5442 HandleCodeCompleteResults(this, CodeCompleter,
5443 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005444 return;
5445 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005446 // Always pretend to enter a context to ensure that a dependent type
5447 // resolves to a dependent record.
5448 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005449 if (!Ctx)
5450 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005451
5452 // Try to instantiate any non-dependent declaration contexts before
5453 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005454 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005455 return;
5456
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005457 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5458 CodeCompleter->getCodeCompletionTUInfo(), CC);
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005459 if (!PreferredType.isNull())
5460 Results.setPreferredType(PreferredType);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005461 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005462
Douglas Gregor3545ff42009-09-21 16:56:56 +00005463 // The "template" keyword can follow "::" in the grammar, but only
5464 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005465 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005466 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005467 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005468
5469 // Add calls to overridden virtual functions, if there are any.
5470 //
5471 // FIXME: This isn't wonderful, because we don't know whether we're actually
5472 // in a context that permits expressions. This is a general issue with
5473 // qualified-id completions.
5474 if (!EnteringContext)
5475 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005476 Results.ExitScope();
5477
Eric Liufead6ae2017-12-13 10:26:49 +00005478 if (CodeCompleter->includeNamespaceLevelDecls() ||
5479 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005480 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005481 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5482 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005483 /*IncludeDependentBases=*/true,
5484 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005485 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005486
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005487 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5488 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005489}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005490
5491void Sema::CodeCompleteUsing(Scope *S) {
5492 if (!CodeCompleter)
5493 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005494
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005495 // This can be both a using alias or using declaration, in the former we
5496 // expect a new name and a symbol in the latter case.
5497 CodeCompletionContext Context(CodeCompletionContext::CCC_SymbolOrNewName);
5498 Context.setIsUsingDeclaration(true);
5499
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005500 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005501 CodeCompleter->getCodeCompletionTUInfo(), Context,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005502 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005503 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005504
Douglas Gregor3545ff42009-09-21 16:56:56 +00005505 // If we aren't in class scope, we could see the "namespace" keyword.
5506 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005507 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005508
5509 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005510 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005511 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005512 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005513 CodeCompleter->includeGlobals(),
5514 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005515 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005516
5517 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5518 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005519}
5520
5521void Sema::CodeCompleteUsingDirective(Scope *S) {
5522 if (!CodeCompleter)
5523 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005524
Douglas Gregor3545ff42009-09-21 16:56:56 +00005525 // After "using namespace", we expect to see a namespace name or namespace
5526 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005527 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005528 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005529 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005530 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005531 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005532 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005533 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005534 CodeCompleter->includeGlobals(),
5535 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005536 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005537 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5538 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005539}
5540
Fangrui Song050229d2018-11-24 00:14:31 +00005541void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005542 if (!CodeCompleter)
5543 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005544
Ted Kremenekc37877d2013-10-08 17:08:03 +00005545 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005546 if (!S->getParent())
5547 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005548
Fangrui Song050229d2018-11-24 00:14:31 +00005549 bool SuppressedGlobalResults =
5550 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005551
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005552 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005553 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005554 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005555 ? CodeCompletionContext::CCC_Namespace
5556 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005557 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005558
Douglas Gregor0ac41382010-09-23 23:01:17 +00005559 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005560 // We only want to see those namespaces that have already been defined
5561 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005562 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005563 // definition of each namespace.
5564 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005565 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005566 NS(Ctx->decls_begin()),
5567 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005568 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005569 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005570
5571 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005572 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005573 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005574 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005575 NS = OrigToLatest.begin(),
5576 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005577 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005578 Results.AddResult(
5579 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5580 nullptr),
5581 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005582 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005583 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005584
Fangrui Song050229d2018-11-24 00:14:31 +00005585 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5586 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005587}
5588
Fangrui Song050229d2018-11-24 00:14:31 +00005589void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005590 if (!CodeCompleter)
5591 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005592
Douglas Gregor3545ff42009-09-21 16:56:56 +00005593 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005594 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005595 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005596 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005597 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005598 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005599 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005600 CodeCompleter->includeGlobals(),
5601 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005602 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5603 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005604}
5605
Douglas Gregorc811ede2009-09-18 20:05:18 +00005606void Sema::CodeCompleteOperatorName(Scope *S) {
5607 if (!CodeCompleter)
5608 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005609
John McCall276321a2010-08-25 06:19:51 +00005610 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005611 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005612 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005613 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005614 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005615 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005616
Richard Smith7fa2b742019-06-14 20:01:51 +00005617 // Add the names of overloadable operators. Note that OO_Conditional is not
5618 // actually overloadable.
Fangrui Song050229d2018-11-24 00:14:31 +00005619#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
Richard Smith7fa2b742019-06-14 20:01:51 +00005620 if (OO_##Name != OO_Conditional) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005621 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005622#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005623
Douglas Gregor3545ff42009-09-21 16:56:56 +00005624 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005625 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005626 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005627 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005628 CodeCompleter->includeGlobals(),
5629 CodeCompleter->loadExternal());
5630
Douglas Gregor3545ff42009-09-21 16:56:56 +00005631 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005632 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005633 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005634
5635 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5636 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005637}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005638
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005639void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005640 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005641 if (!ConstructorD)
5642 return;
5643
5644 AdjustDeclIfTemplate(ConstructorD);
5645
Fangrui Song050229d2018-11-24 00:14:31 +00005646 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005647 if (!Constructor)
5648 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005649
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005651 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005652 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005653 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005654
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005655 // Fill in any already-initialized fields or base classes.
5656 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5657 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005658 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005659 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005660 InitializedBases.insert(Context.getCanonicalType(
5661 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005662 else
Fangrui Song050229d2018-11-24 00:14:31 +00005663 InitializedFields.insert(
5664 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005665 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005666
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005667 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005668 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005669 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005670 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005671
5672 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5673 CodeCompletionBuilder Builder(Results.getAllocator(),
5674 Results.getCodeCompletionTUInfo());
5675 Builder.AddTypedTextChunk(Name);
5676 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005677 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005678 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005679 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005680 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5681 Builder);
5682 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5683 return Builder.TakeString();
5684 };
5685 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5686 const NamedDecl *ND) {
5687 CodeCompletionBuilder Builder(Results.getAllocator(),
5688 Results.getCodeCompletionTUInfo());
5689 Builder.AddTypedTextChunk(Name);
5690 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5691 Builder.AddPlaceholderChunk(Type);
5692 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5693 if (ND) {
5694 auto CCR = CodeCompletionResult(
5695 Builder.TakeString(), ND,
5696 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5697 if (isa<FieldDecl>(ND))
5698 CCR.CursorKind = CXCursor_MemberRef;
5699 return Results.AddResult(CCR);
5700 }
5701 return Results.AddResult(CodeCompletionResult(
5702 Builder.TakeString(),
5703 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5704 };
5705 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5706 const char *Name, const FieldDecl *FD) {
5707 if (!RD)
5708 return AddDefaultCtorInit(Name,
5709 FD ? Results.getAllocator().CopyString(
5710 FD->getType().getAsString(Policy))
5711 : Name,
5712 FD);
5713 auto Ctors = getConstructors(Context, RD);
5714 if (Ctors.begin() == Ctors.end())
5715 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005716 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005717 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5718 CCR.CursorKind = getCursorKindForDecl(Ctor);
5719 Results.AddResult(CCR);
5720 }
5721 };
5722 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5723 const char *BaseName =
5724 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5725 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5726 AddCtorsWithName(
5727 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5728 BaseName, nullptr);
5729 };
5730 auto AddField = [&](const FieldDecl *FD) {
5731 const char *FieldName =
5732 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5733 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5734 AddCtorsWithName(
5735 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5736 FieldName, FD);
5737 };
5738
Aaron Ballman574705e2014-03-13 15:41:46 +00005739 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005740 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5741 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005742 SawLastInitializer =
5743 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5744 Context.hasSameUnqualifiedType(
5745 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005746 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005747 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005748
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005749 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005750 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005751 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005752
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005753 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005754 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005755 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5756 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005757 SawLastInitializer =
5758 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5759 Context.hasSameUnqualifiedType(
5760 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005761 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005762 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005763
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005764 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005765 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005766 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005767
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005768 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005769 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005770 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5771 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005772 SawLastInitializer = !Initializers.empty() &&
5773 Initializers.back()->isAnyMemberInitializer() &&
5774 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005775 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005776 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005777
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005778 if (!Field->getDeclName())
5779 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005780
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005781 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005782 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005783 }
5784 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005785
Douglas Gregor0ac41382010-09-23 23:01:17 +00005786 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005787 Results.data(), Results.size());
5788}
5789
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005790/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005791static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005792 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005793 if (!DC)
5794 return false;
5795
5796 return DC->isFileContext();
5797}
5798
5799void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5800 bool AfterAmpersand) {
5801 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005802 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005803 CodeCompletionContext::CCC_Other);
5804 Results.EnterNewScope();
5805
5806 // Note what has already been captured.
5807 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5808 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005809 for (const auto &C : Intro.Captures) {
5810 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005811 IncludedThis = true;
5812 continue;
5813 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005814
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005815 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005816 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005817
Douglas Gregord8c61782012-02-15 15:34:24 +00005818 // Look for other capturable variables.
5819 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005820 for (const auto *D : S->decls()) {
5821 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005822 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005823 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005824
David Blaikie82e95a32014-11-19 07:49:47 +00005825 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005826 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005827 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005828 }
5829 }
5830
5831 // Add 'this', if it would be valid.
5832 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5833 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005834
Douglas Gregord8c61782012-02-15 15:34:24 +00005835 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005836
Douglas Gregord8c61782012-02-15 15:34:24 +00005837 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5838 Results.data(), Results.size());
5839}
5840
James Dennett596e4752012-06-14 03:11:41 +00005841/// Macro that optionally prepends an "@" to the string literal passed in via
5842/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005843#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005844
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005845static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005846 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005847 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005848 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005849 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005850
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005851 CodeCompletionBuilder Builder(Results.getAllocator(),
5852 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005853 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005854 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005855 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5857 Builder.AddPlaceholderChunk("property");
5858 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005859
Douglas Gregorf1934162010-01-13 21:24:21 +00005860 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005861 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005862 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5863 Builder.AddPlaceholderChunk("property");
5864 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005865 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005866}
5867
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005868static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005869 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005870 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005871
Douglas Gregorf1934162010-01-13 21:24:21 +00005872 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005873 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005874
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005875 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005876 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005877 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005878
Douglas Gregorf1934162010-01-13 21:24:21 +00005879 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005880 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005881
Douglas Gregorf1934162010-01-13 21:24:21 +00005882 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005883 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005884 }
5885}
5886
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005887static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005888 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005889 CodeCompletionBuilder Builder(Results.getAllocator(),
5890 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005891
Douglas Gregorf1934162010-01-13 21:24:21 +00005892 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005893 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005894 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5895 Builder.AddPlaceholderChunk("name");
5896 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005897
Douglas Gregorf4c33342010-05-28 00:22:41 +00005898 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005899 // @interface name
5900 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005901 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005902 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5904 Builder.AddPlaceholderChunk("class");
5905 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005906
Douglas Gregorf4c33342010-05-28 00:22:41 +00005907 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005908 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5910 Builder.AddPlaceholderChunk("protocol");
5911 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005912
Douglas Gregorf4c33342010-05-28 00:22:41 +00005913 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005914 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5916 Builder.AddPlaceholderChunk("class");
5917 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005918 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005919
Douglas Gregorf1934162010-01-13 21:24:21 +00005920 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005921 Builder.AddTypedTextChunk(
5922 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005923 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5924 Builder.AddPlaceholderChunk("alias");
5925 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5926 Builder.AddPlaceholderChunk("class");
5927 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005928
5929 if (Results.getSema().getLangOpts().Modules) {
5930 // @import name
5931 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5932 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5933 Builder.AddPlaceholderChunk("module");
5934 Results.AddResult(Result(Builder.TakeString()));
5935 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005936}
5937
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005938void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005939 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005940 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005941 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005942 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005943 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005944 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005945 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005946 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005947 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005948 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005949 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005950 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5951 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005952}
5953
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005954static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005955 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005956 CodeCompletionBuilder Builder(Results.getAllocator(),
5957 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005958
5959 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005960 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005961 if (Results.getSema().getLangOpts().CPlusPlus ||
5962 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005963 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005964 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005965 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005966 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5967 Builder.AddPlaceholderChunk("type-name");
5968 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5969 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005970
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005971 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005972 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005973 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005974 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5975 Builder.AddPlaceholderChunk("protocol-name");
5976 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5977 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005978
5979 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005980 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005981 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005982 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5983 Builder.AddPlaceholderChunk("selector");
5984 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5985 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005986
5987 // @"string"
5988 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005989 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005990 Builder.AddPlaceholderChunk("string");
5991 Builder.AddTextChunk("\"");
5992 Results.AddResult(Result(Builder.TakeString()));
5993
Douglas Gregor951de302012-07-17 23:24:47 +00005994 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005995 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005996 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005997 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005998 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5999 Results.AddResult(Result(Builder.TakeString()));
6000
Douglas Gregor951de302012-07-17 23:24:47 +00006001 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00006002 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00006003 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00006004 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00006005 Builder.AddChunk(CodeCompletionString::CK_Colon);
6006 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6007 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00006008 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
6009 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00006010
Douglas Gregor951de302012-07-17 23:24:47 +00006011 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00006012 Builder.AddResultTypeChunk("id");
6013 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00006014 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00006015 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6016 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006017}
6018
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006019static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00006020 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006021 CodeCompletionBuilder Builder(Results.getAllocator(),
6022 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006023
Douglas Gregorf4c33342010-05-28 00:22:41 +00006024 if (Results.includeCodePatterns()) {
6025 // @try { statements } @catch ( declaration ) { statements } @finally
6026 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00006027 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006028 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6029 Builder.AddPlaceholderChunk("statements");
6030 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
6031 Builder.AddTextChunk("@catch");
6032 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6033 Builder.AddPlaceholderChunk("parameter");
6034 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6035 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6036 Builder.AddPlaceholderChunk("statements");
6037 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
6038 Builder.AddTextChunk("@finally");
6039 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6040 Builder.AddPlaceholderChunk("statements");
6041 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
6042 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00006043 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006044
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006045 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00006046 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006047 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6048 Builder.AddPlaceholderChunk("expression");
6049 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006050
Douglas Gregorf4c33342010-05-28 00:22:41 +00006051 if (Results.includeCodePatterns()) {
6052 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00006053 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006054 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6055 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6056 Builder.AddPlaceholderChunk("expression");
6057 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6058 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6059 Builder.AddPlaceholderChunk("statements");
6060 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
6061 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00006062 }
Douglas Gregorf1934162010-01-13 21:24:21 +00006063}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006064
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006065static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00006066 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00006067 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006068 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
6069 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
6070 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00006071 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00006072 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00006073}
6074
6075void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006076 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006077 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006078 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00006079 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00006080 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00006081 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006082 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6083 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00006084}
6085
6086void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006087 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006088 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006089 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00006090 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006091 AddObjCStatementResults(Results, false);
6092 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006093 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006094 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6095 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006096}
6097
6098void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006099 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006100 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006101 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006102 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006103 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006104 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006105 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6106 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006107}
6108
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006109/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00006110/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00006111static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00006112 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00006113 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00006114 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006115
Bill Wendling44426052012-12-20 19:22:21 +00006116 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006117
Douglas Gregore6078da2009-11-19 00:14:45 +00006118 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00006119 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
6120 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00006121 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006122
Jordan Rose53cb2f32012-08-20 20:01:13 +00006123 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00006124 unsigned AssignCopyRetMask =
6125 Attributes &
6126 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
6127 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
6128 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
6129 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00006130 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00006131 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00006132 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00006133 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
6134 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00006135 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006136
Douglas Gregore6078da2009-11-19 00:14:45 +00006137 return false;
6138}
6139
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006140void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00006141 if (!CodeCompleter)
6142 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006143
Bill Wendling44426052012-12-20 19:22:21 +00006144 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006145
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006146 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006147 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006148 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00006149 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00006150 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00006151 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00006152 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00006153 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00006154 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00006155 ObjCDeclSpec::DQ_PR_unsafe_unretained))
6156 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00006157 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00006158 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00006159 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00006160 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00006161 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00006162 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00006163 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00006164 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00006165 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00006166 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00006167 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00006168 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00006169
6170 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00006171 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00006172 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00006173 Results.AddResult(CodeCompletionResult("weak"));
6174
Bill Wendling44426052012-12-20 19:22:21 +00006175 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006176 CodeCompletionBuilder Setter(Results.getAllocator(),
6177 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006178 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006179 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006180 Setter.AddPlaceholderChunk("method");
6181 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006182 }
Bill Wendling44426052012-12-20 19:22:21 +00006183 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006184 CodeCompletionBuilder Getter(Results.getAllocator(),
6185 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006186 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006187 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006188 Getter.AddPlaceholderChunk("method");
6189 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006190 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006191 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
6192 Results.AddResult(CodeCompletionResult("nonnull"));
6193 Results.AddResult(CodeCompletionResult("nullable"));
6194 Results.AddResult(CodeCompletionResult("null_unspecified"));
6195 Results.AddResult(CodeCompletionResult("null_resettable"));
6196 }
Steve Naroff936354c2009-10-08 21:55:05 +00006197 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006198 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6199 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00006200}
Steve Naroffeae65032009-11-07 02:08:14 +00006201
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006202/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00006203/// via code completion.
6204enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00006205 MK_Any, ///< Any kind of method, provided it means other specified criteria.
6206 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00006207 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006208};
6209
Fangrui Song050229d2018-11-24 00:14:31 +00006210static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006211 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006212 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006213 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006214 if (NumSelIdents > Sel.getNumArgs())
6215 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006216
Douglas Gregor67c692c2010-08-26 15:07:07 +00006217 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00006218 case MK_Any:
6219 break;
6220 case MK_ZeroArgSelector:
6221 return Sel.isUnarySelector();
6222 case MK_OneArgSelector:
6223 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006224 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006225
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006226 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
6227 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006228
Douglas Gregor67c692c2010-08-26 15:07:07 +00006229 for (unsigned I = 0; I != NumSelIdents; ++I)
6230 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
6231 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006232
Douglas Gregor67c692c2010-08-26 15:07:07 +00006233 return true;
6234}
6235
Douglas Gregorc8537c52009-11-19 07:41:15 +00006236static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
6237 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006238 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006239 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006240 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006241 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006242}
Douglas Gregor1154e272010-09-16 16:06:31 +00006243
Fangrui Song050229d2018-11-24 00:14:31 +00006244/// A set of selectors, which is used to avoid introducing multiple
6245/// completions with the same selector into the result set.
6246typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00006247
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006248/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006249/// container to the set of results.
6250///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006251/// The container will be a class, protocol, category, or implementation of
6252/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006253/// the superclasses of classes along with their categories, protocols, and
6254/// implementations.
6255///
6256/// \param Container the container in which we'll look to find methods.
6257///
James Dennett596e4752012-06-14 03:11:41 +00006258/// \param WantInstanceMethods Whether to add instance methods (only); if
6259/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006260///
6261/// \param CurContext the context in which we're performing the lookup that
6262/// finds methods.
6263///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006264/// \param AllowSameLength Whether we allow a method to be added to the list
6265/// when it has the same number of parameters as we have selector identifiers.
6266///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006267/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006268static void AddObjCMethods(ObjCContainerDecl *Container,
6269 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006270 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006271 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006272 VisitedSelectorSet &Selectors, bool AllowSameLength,
6273 ResultBuilder &Results, bool InOriginalClass = true,
6274 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00006275 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006276 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00006277 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00006278 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00006279 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00006280 // The instance methods on the root class can be messaged via the
6281 // metaclass.
6282 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00006283 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006284 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00006285 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006286 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00006287 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00006288
David Blaikie82e95a32014-11-19 07:49:47 +00006289 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006290 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006291
6292 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006293 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00006294 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00006295 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00006296 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00006297 Results.MaybeAddResult(R, CurContext);
6298 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006299 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006300
Douglas Gregorf37c9492010-09-16 15:34:59 +00006301 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006302 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00006303 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006304 const ObjCList<ObjCProtocolDecl> &Protocols =
6305 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006306 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006307 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006308 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006309 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6310 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00006311 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00006312 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006313
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006314 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006315 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006316
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006317 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006318 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006319 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6320 Selectors, AllowSameLength, Results, false, IsRootClass);
6321
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006322 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00006323 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006324 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006325 CurContext, Selectors, AllowSameLength, Results,
6326 InOriginalClass, IsRootClass);
6327
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006328 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00006329 const ObjCList<ObjCProtocolDecl> &Protocols =
6330 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006331 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6332 E = Protocols.end();
6333 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006334 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6335 Selectors, AllowSameLength, Results, false, IsRootClass);
6336
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006337 // Add methods in category implementations.
6338 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006339 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6340 Selectors, AllowSameLength, Results, InOriginalClass,
6341 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006342 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006343
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006344 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006345 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006346 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006347 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6348 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6349 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006350
6351 // Add methods in our implementation, if any.
6352 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006353 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6354 Selectors, AllowSameLength, Results, InOriginalClass,
6355 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006356}
6357
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006358void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006359 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006360 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006361 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006362 if (ObjCCategoryDecl *Category =
6363 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006364 Class = Category->getClassInterface();
6365
6366 if (!Class)
6367 return;
6368 }
6369
6370 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006371 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006372 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006373 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006374 Results.EnterNewScope();
6375
Douglas Gregor1154e272010-09-16 16:06:31 +00006376 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006377 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006378 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006379 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006380 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6381 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006382}
6383
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006384void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006385 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006386 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006387 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006388 if (ObjCCategoryDecl *Category =
6389 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006390 Class = Category->getClassInterface();
6391
6392 if (!Class)
6393 return;
6394 }
6395
6396 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006397 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006398 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006399 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006400 Results.EnterNewScope();
6401
Douglas Gregor1154e272010-09-16 16:06:31 +00006402 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006403 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6404 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006405
6406 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006407 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6408 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006409}
6410
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006411void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6412 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006413 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006414 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006415 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006416 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006417
Douglas Gregor99fa2642010-08-24 01:06:58 +00006418 // Add context-sensitive, Objective-C parameter-passing keywords.
6419 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006420 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006421 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6422 Results.AddResult("in");
6423 Results.AddResult("inout");
6424 AddedInOut = true;
6425 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006426 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006427 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6428 Results.AddResult("out");
6429 if (!AddedInOut)
6430 Results.AddResult("inout");
6431 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006432 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006433 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6434 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006435 Results.AddResult("bycopy");
6436 Results.AddResult("byref");
6437 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006438 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006439 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6440 Results.AddResult("nonnull");
6441 Results.AddResult("nullable");
6442 Results.AddResult("null_unspecified");
6443 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006444
6445 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006446 // identifier IBAction refers to a macro, provide a completion item for
6447 // an action, e.g.,
6448 // IBAction)<#selector#>:(id)sender
6449 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006450 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006451 CodeCompletionBuilder Builder(Results.getAllocator(),
6452 Results.getCodeCompletionTUInfo(),
6453 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006454 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006455 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006456 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006457 Builder.AddChunk(CodeCompletionString::CK_Colon);
6458 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006459 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006460 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006461 Builder.AddTextChunk("sender");
6462 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6463 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006464
6465 // If we're completing the return type, provide 'instancetype'.
6466 if (!IsParameter) {
6467 Results.AddResult(CodeCompletionResult("instancetype"));
6468 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006469
Douglas Gregor99fa2642010-08-24 01:06:58 +00006470 // Add various builtin type names and specifiers.
6471 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6472 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006473
Douglas Gregor99fa2642010-08-24 01:06:58 +00006474 // Add the various type names
6475 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6476 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6477 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006478 CodeCompleter->includeGlobals(),
6479 CodeCompleter->loadExternal());
6480
Douglas Gregor99fa2642010-08-24 01:06:58 +00006481 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006482 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006483
Eric Liuf5ba09f2018-07-04 10:01:18 +00006484 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006485 Results.data(), Results.size());
6486}
6487
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006488/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006489/// that it has some more-specific class type based on knowledge of
6490/// common uses of Objective-C. This routine returns that class type,
6491/// or NULL if no better result could be determined.
6492static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006493 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006494 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006495 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006496
6497 Selector Sel = Msg->getSelector();
6498 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006499 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006500
6501 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6502 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006503 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006504
6505 ObjCMethodDecl *Method = Msg->getMethodDecl();
6506 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006507 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006508
6509 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006510 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006511 switch (Msg->getReceiverKind()) {
6512 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006513 if (const ObjCObjectType *ObjType =
6514 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006515 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006516 break;
6517
6518 case ObjCMessageExpr::Instance: {
6519 QualType T = Msg->getInstanceReceiver()->getType();
6520 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6521 IFace = Ptr->getInterfaceDecl();
6522 break;
6523 }
6524
6525 case ObjCMessageExpr::SuperInstance:
6526 case ObjCMessageExpr::SuperClass:
6527 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006528 }
6529
6530 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006531 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006532
6533 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6534 if (Method->isInstanceMethod())
6535 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006536 .Case("retain", IFace)
6537 .Case("strong", IFace)
6538 .Case("autorelease", IFace)
6539 .Case("copy", IFace)
6540 .Case("copyWithZone", IFace)
6541 .Case("mutableCopy", IFace)
6542 .Case("mutableCopyWithZone", IFace)
6543 .Case("awakeFromCoder", IFace)
6544 .Case("replacementObjectFromCoder", IFace)
6545 .Case("class", IFace)
6546 .Case("classForCoder", IFace)
6547 .Case("superclass", Super)
6548 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006549
6550 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006551 .Case("new", IFace)
6552 .Case("alloc", IFace)
6553 .Case("allocWithZone", IFace)
6554 .Case("class", IFace)
6555 .Case("superclass", Super)
6556 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006557}
6558
Douglas Gregor6fc04132010-08-27 15:10:57 +00006559// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006560// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006561// function.
6562///
6563/// \param S The semantic analysis object.
6564///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006565/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006566/// the "super" keyword. Otherwise, we just need to provide the arguments.
6567///
6568/// \param SelIdents The identifiers in the selector that have already been
6569/// provided as arguments for a send to "super".
6570///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006571/// \param Results The set of results to augment.
6572///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006573/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006574/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006575static ObjCMethodDecl *
6576AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6577 ArrayRef<IdentifierInfo *> SelIdents,
6578 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006579 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6580 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006581 return nullptr;
6582
Douglas Gregor6fc04132010-08-27 15:10:57 +00006583 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6584 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006585 return nullptr;
6586
Douglas Gregor6fc04132010-08-27 15:10:57 +00006587 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006588 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006589 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6590 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006591 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006592 CurMethod->isInstanceMethod());
6593
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006594 // Check in categories or class extensions.
6595 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006596 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006597 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006598 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006599 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006600 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006601 }
6602 }
6603
Douglas Gregor6fc04132010-08-27 15:10:57 +00006604 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006605 return nullptr;
6606
Douglas Gregor6fc04132010-08-27 15:10:57 +00006607 // Check whether the superclass method has the same signature.
6608 if (CurMethod->param_size() != SuperMethod->param_size() ||
6609 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006610 return nullptr;
6611
Douglas Gregor6fc04132010-08-27 15:10:57 +00006612 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006613 CurPEnd = CurMethod->param_end(),
6614 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006615 CurP != CurPEnd; ++CurP, ++SuperP) {
6616 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006617 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006618 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006619 return nullptr;
6620
Douglas Gregor6fc04132010-08-27 15:10:57 +00006621 // Make sure we have a parameter name to forward!
6622 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006623 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006624 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006625
Douglas Gregor6fc04132010-08-27 15:10:57 +00006626 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006627 CodeCompletionBuilder Builder(Results.getAllocator(),
6628 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006629
Douglas Gregor6fc04132010-08-27 15:10:57 +00006630 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006631 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006632 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006633
6634 // If we need the "super" keyword, add it (plus some spacing).
6635 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006636 Builder.AddTypedTextChunk("super");
6637 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006638 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006639
Douglas Gregor6fc04132010-08-27 15:10:57 +00006640 Selector Sel = CurMethod->getSelector();
6641 if (Sel.isUnarySelector()) {
6642 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006643 Builder.AddTextChunk(
6644 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006645 else
Fangrui Song050229d2018-11-24 00:14:31 +00006646 Builder.AddTypedTextChunk(
6647 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006648 } else {
6649 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6650 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006651 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006652 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006653
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006654 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006655 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006656 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006657 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006658 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006659 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006660 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006661 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006662 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006663 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006664 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006665 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006666 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006667 }
6668 }
6669 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006670
Douglas Gregor78254c82012-03-27 23:34:16 +00006671 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6672 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006673 return SuperMethod;
6674}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006675
Douglas Gregora817a192010-05-27 23:06:34 +00006676void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006677 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006678 ResultBuilder Results(
6679 *this, CodeCompleter->getAllocator(),
6680 CodeCompleter->getCodeCompletionTUInfo(),
6681 CodeCompletionContext::CCC_ObjCMessageReceiver,
6682 getLangOpts().CPlusPlus11
6683 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6684 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006685
Douglas Gregora817a192010-05-27 23:06:34 +00006686 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6687 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006688 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006689 CodeCompleter->includeGlobals(),
6690 CodeCompleter->loadExternal());
6691
Douglas Gregora817a192010-05-27 23:06:34 +00006692 // If we are in an Objective-C method inside a class that has a superclass,
6693 // add "super" as an option.
6694 if (ObjCMethodDecl *Method = getCurMethodDecl())
6695 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006696 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006697 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006698
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006699 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006700 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006701
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006702 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006703 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006704
Douglas Gregora817a192010-05-27 23:06:34 +00006705 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006706
Douglas Gregora817a192010-05-27 23:06:34 +00006707 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006708 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006709 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006710 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006711}
6712
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006713void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006714 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006715 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006716 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006717 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6718 // Figure out which interface we're in.
6719 CDecl = CurMethod->getClassInterface();
6720 if (!CDecl)
6721 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006722
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006723 // Find the superclass of this class.
6724 CDecl = CDecl->getSuperClass();
6725 if (!CDecl)
6726 return;
6727
6728 if (CurMethod->isInstanceMethod()) {
6729 // We are inside an instance method, which means that the message
6730 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006731 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006732 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006733 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006734 }
6735
6736 // Fall through to send to the superclass in CDecl.
6737 } else {
6738 // "super" may be the name of a type or variable. Figure out which
6739 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006740 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006741 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006742 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6743 // "super" names an interface. Use it.
6744 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006745 if (const ObjCObjectType *Iface =
6746 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006747 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006748 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6749 // "super" names an unresolved type; we can't be more specific.
6750 } else {
6751 // Assume that "super" names some kind of value and parse that way.
6752 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006753 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006754 UnqualifiedId id;
6755 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006756 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6757 /*HasTrailingLParen=*/false,
6758 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006759 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006760 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006761 }
6762
6763 // Fall through
6764 }
6765
John McCallba7bf592010-08-24 05:47:05 +00006766 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006767 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006768 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006769 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006770 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006771 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006772}
6773
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006774/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006775/// send, determine the preferred type (if any) for that argument expression.
6776static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6777 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006778 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006779 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006780
Douglas Gregor74661272010-09-21 00:03:25 +00006781 QualType PreferredType;
6782 unsigned BestPriority = CCP_Unlikely * 2;
6783 Result *ResultsData = Results.data();
6784 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6785 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006786 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006787 isa<ObjCMethodDecl>(R.Declaration)) {
6788 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006789 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006790 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006791 QualType MyPreferredType =
6792 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006793 if (R.Priority < BestPriority || PreferredType.isNull()) {
6794 BestPriority = R.Priority;
6795 PreferredType = MyPreferredType;
6796 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6797 MyPreferredType)) {
6798 PreferredType = QualType();
6799 }
6800 }
6801 }
6802 }
6803 }
6804
6805 return PreferredType;
6806}
6807
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006808static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006809 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006810 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006811 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006812 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006813 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006814 ObjCInterfaceDecl *CDecl = nullptr;
6815
Douglas Gregor8ce33212009-11-17 17:59:40 +00006816 // If the given name refers to an interface type, retrieve the
6817 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006818 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006819 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006820 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006821 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6822 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006823 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006824
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006825 // Add all of the factory methods in this Objective-C class, its protocols,
6826 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006827 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006828
6829 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006830 // completion.
6831 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006832 if (ObjCMethodDecl *SuperMethod =
6833 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006834 Results.Ignore(SuperMethod);
6835 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006836
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006837 // If we're inside an Objective-C method definition, prefer its selector to
6838 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006839 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006840 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006841
Douglas Gregor1154e272010-09-16 16:06:31 +00006842 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006843 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006844 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6845 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006846 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006847 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006848
Douglas Gregord720daf2010-04-06 17:30:22 +00006849 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006850 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006851 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006852 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006853 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006854 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006855 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006856 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006857 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006858
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006859 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006860 }
6861 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006862
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006863 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006864 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006865 M != MEnd; ++M) {
6866 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006867 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006868 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006869 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006870
Nico Weber2e0c8f72014-12-27 03:58:08 +00006871 Result R(MethList->getMethod(),
6872 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006873 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006874 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006875 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006876 }
6877 }
6878 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006879
6880 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006881}
Douglas Gregor6285f752010-04-06 16:40:00 +00006882
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006883void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006884 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006885 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006886 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006887
Douglas Gregor63745d52011-07-21 01:05:26 +00006888 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006889
Fangrui Song050229d2018-11-24 00:14:31 +00006890 ResultBuilder Results(
6891 *this, CodeCompleter->getAllocator(),
6892 CodeCompleter->getCodeCompletionTUInfo(),
6893 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6894 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006895
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006896 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006897 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006898
6899 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006900 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006901 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006902 // code-complete the expression using the corresponding parameter type as
6903 // our preferred type, improving completion results.
6904 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006905 QualType PreferredType =
6906 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006907 if (PreferredType.isNull())
6908 CodeCompleteOrdinaryName(S, PCC_Expression);
6909 else
6910 CodeCompleteExpression(S, PreferredType);
6911 return;
6912 }
6913
Fangrui Song050229d2018-11-24 00:14:31 +00006914 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006915 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006916}
6917
Richard Trieu2bd04012011-09-09 02:00:50 +00006918void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006919 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006920 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006921 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006922 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006923
Steve Naroffeae65032009-11-07 02:08:14 +00006924 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006925
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006926 // If necessary, apply function/array conversion to the receiver.
6927 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006928 if (RecExpr) {
6929 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6930 if (Conv.isInvalid()) // conversion failed. bail.
6931 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006932 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006933 }
Fangrui Song050229d2018-11-24 00:14:31 +00006934 QualType ReceiverType = RecExpr
6935 ? RecExpr->getType()
6936 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006937 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006938 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006939
Douglas Gregordc520b02010-11-08 21:12:30 +00006940 // If we're messaging an expression with type "id" or "Class", check
6941 // whether we know something special about the receiver that allows
6942 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006943 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006944 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6945 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006946 return CodeCompleteObjCClassMessage(
6947 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6948 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006949
Fangrui Song050229d2018-11-24 00:14:31 +00006950 ReceiverType =
6951 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006952 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006953 } else if (RecExpr && getLangOpts().CPlusPlus) {
6954 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6955 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006956 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006957 ReceiverType = RecExpr->getType();
6958 }
6959 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006960
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006961 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006962 ResultBuilder Results(
6963 *this, CodeCompleter->getAllocator(),
6964 CodeCompleter->getCodeCompletionTUInfo(),
6965 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6966 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006967
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006968 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006969
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006970 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006971 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006972 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006973 if (ObjCMethodDecl *SuperMethod =
6974 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006975 Results.Ignore(SuperMethod);
6976 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006977
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006978 // If we're inside an Objective-C method definition, prefer its selector to
6979 // others.
6980 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6981 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006982
Douglas Gregor1154e272010-09-16 16:06:31 +00006983 // Keep track of the selectors we've already added.
6984 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006985
Douglas Gregora3329fa2009-11-18 00:06:18 +00006986 // Handle messages to Class. This really isn't a message to an instance
6987 // method, so we treat it the same way we would treat a message send to a
6988 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006989 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006990 ReceiverType->isObjCQualifiedClassType()) {
6991 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6992 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006993 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6994 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006995 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006996 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006997 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006998 else if (const ObjCObjectPointerType *QualID =
6999 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00007000 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00007001 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00007002 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
7003 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00007004 }
7005 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00007006 else if (const ObjCObjectPointerType *IFacePtr =
7007 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00007008 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00007009 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00007010 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007011
Douglas Gregora3329fa2009-11-18 00:06:18 +00007012 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00007013 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00007014 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
7015 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00007016 }
Douglas Gregor6285f752010-04-06 16:40:00 +00007017 // Handle messages to "id".
7018 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00007019 // We're messaging "id", so provide all instance methods we know
7020 // about as code-completion results.
7021
7022 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007023 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00007024 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00007025 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7026 I != N; ++I) {
7027 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007028 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00007029 continue;
7030
Sebastian Redl75d8a322010-08-02 23:18:59 +00007031 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00007032 }
7033 }
7034
Sebastian Redl75d8a322010-08-02 23:18:59 +00007035 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7036 MEnd = MethodPool.end();
7037 M != MEnd; ++M) {
7038 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00007039 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007040 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00007041 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007042
Nico Weber2e0c8f72014-12-27 03:58:08 +00007043 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00007044 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00007045
Nico Weber2e0c8f72014-12-27 03:58:08 +00007046 Result R(MethList->getMethod(),
7047 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007048 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00007049 R.AllParametersAreInformative = false;
7050 Results.MaybeAddResult(R, CurContext);
7051 }
7052 }
7053 }
Steve Naroffeae65032009-11-07 02:08:14 +00007054 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007055
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007056 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00007057 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007058 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00007059 // code-complete the expression using the corresponding parameter type as
7060 // our preferred type, improving completion results.
7061 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00007062 QualType PreferredType =
7063 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00007064 if (PreferredType.isNull())
7065 CodeCompleteOrdinaryName(S, PCC_Expression);
7066 else
7067 CodeCompleteExpression(S, PreferredType);
7068 return;
7069 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007070
Fangrui Song050229d2018-11-24 00:14:31 +00007071 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7072 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00007073}
Douglas Gregorbaf69612009-11-18 04:19:12 +00007074
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007075void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00007076 DeclGroupPtrTy IterationVar) {
7077 CodeCompleteExpressionData Data;
7078 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007079
Douglas Gregor68762e72010-08-23 21:17:50 +00007080 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00007081 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00007082 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
7083 if (*I)
7084 Data.IgnoreDecls.push_back(*I);
7085 }
7086 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007087
Douglas Gregor68762e72010-08-23 21:17:50 +00007088 CodeCompleteExpression(S, Data);
7089}
7090
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007091void Sema::CodeCompleteObjCSelector(Scope *S,
7092 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007093 // If we have an external source, load the entire class method
7094 // pool from the AST file.
7095 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00007096 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
7097 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007098 Selector Sel = ExternalSource->GetExternalSelector(I);
7099 if (Sel.isNull() || MethodPool.count(Sel))
7100 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007101
Douglas Gregor67c692c2010-08-26 15:07:07 +00007102 ReadMethodPool(Sel);
7103 }
7104 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007105
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007106 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007107 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007108 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00007109 Results.EnterNewScope();
7110 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007111 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00007112 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007113
Douglas Gregor67c692c2010-08-26 15:07:07 +00007114 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007115 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00007116 continue;
7117
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007118 CodeCompletionBuilder Builder(Results.getAllocator(),
7119 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007120 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007121 Builder.AddTypedTextChunk(
7122 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007123 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007124 continue;
7125 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007126
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007127 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00007128 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007129 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007130 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007131 Builder.AddInformativeChunk(
7132 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007133 Accumulator.clear();
7134 }
7135 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007136
Benjamin Kramer632500c2011-07-26 16:59:25 +00007137 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007138 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00007139 }
Fangrui Song050229d2018-11-24 00:14:31 +00007140 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007141 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007142 }
7143 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007144
7145 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00007146 Results.data(), Results.size());
7147}
7148
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007149/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00007150/// (translation unit) context.
7151static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007152 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00007153 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007154 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007155
Aaron Ballman629afae2014-03-07 19:56:05 +00007156 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00007157 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007158 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00007159 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00007160 Results.AddResult(
7161 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
7162 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007163 }
7164}
7165
Craig Topper883dd332015-12-24 23:58:11 +00007166void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00007167 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007168 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007169 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007170 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007171
Chandler Carruthede11632016-11-04 06:06:50 +00007172 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007173 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007174
Douglas Gregora3b23b02010-12-09 21:44:02 +00007175 // Tell the result set to ignore all of the protocols we have
7176 // already seen.
7177 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00007178 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00007179 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00007180 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007181
Douglas Gregora3b23b02010-12-09 21:44:02 +00007182 // Add all protocols.
7183 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
7184 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007185
Douglas Gregora3b23b02010-12-09 21:44:02 +00007186 Results.ExitScope();
7187 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00007188
7189 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7190 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007191}
7192
7193void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007194 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007195 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007196 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007197
Chandler Carruthede11632016-11-04 06:06:50 +00007198 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007199 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007200
Douglas Gregora3b23b02010-12-09 21:44:02 +00007201 // Add all protocols.
7202 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
7203 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007204
Douglas Gregora3b23b02010-12-09 21:44:02 +00007205 Results.ExitScope();
7206 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00007207
7208 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7209 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00007210}
Douglas Gregor49c22a72009-11-18 16:26:39 +00007211
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007212/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00007213/// the given (translation unit) context.
7214static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
7215 bool OnlyForwardDeclarations,
7216 bool OnlyUnimplemented,
7217 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007218 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007219
Aaron Ballman629afae2014-03-07 19:56:05 +00007220 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00007221 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007222 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00007223 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00007224 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00007225 Results.AddResult(
7226 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
7227 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007228 }
7229}
7230
Eric Liuf5ba09f2018-07-04 10:01:18 +00007231void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007232 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007233 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007234 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007235 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007236
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007237 if (CodeCompleter->includeGlobals()) {
7238 // Add all classes.
7239 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7240 false, Results);
7241 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007242
Douglas Gregor49c22a72009-11-18 16:26:39 +00007243 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007244
Eric Liuf5ba09f2018-07-04 10:01:18 +00007245 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7246 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007247}
7248
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007249void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007250 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007251 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007252 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007253 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007254 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007255
Douglas Gregor49c22a72009-11-18 16:26:39 +00007256 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00007257 NamedDecl *CurClass =
7258 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007259 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00007260 Results.Ignore(CurClass);
7261
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007262 if (CodeCompleter->includeGlobals()) {
7263 // Add all classes.
7264 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7265 false, Results);
7266 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007267
Douglas Gregor49c22a72009-11-18 16:26:39 +00007268 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007269
Eric Liuf5ba09f2018-07-04 10:01:18 +00007270 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7271 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007272}
7273
Eric Liuf5ba09f2018-07-04 10:01:18 +00007274void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007275 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007276 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007277 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007278 Results.EnterNewScope();
7279
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007280 if (CodeCompleter->includeGlobals()) {
7281 // Add all unimplemented classes.
7282 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7283 true, Results);
7284 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007285
Douglas Gregor49c22a72009-11-18 16:26:39 +00007286 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007287
Eric Liuf5ba09f2018-07-04 10:01:18 +00007288 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7289 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007290}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007291
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007292void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007293 IdentifierInfo *ClassName,
7294 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007295 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007296
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007297 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007298 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007299 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007300
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007301 // Ignore any categories we find that have already been implemented by this
7302 // interface.
7303 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00007304 NamedDecl *CurClass =
7305 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
7306 if (ObjCInterfaceDecl *Class =
7307 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007308 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007309 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007310 }
7311
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007312 // Add all of the categories we know about.
7313 Results.EnterNewScope();
7314 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007315 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00007316 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00007317 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00007318 Results.AddResult(
7319 Result(Category, Results.getBasePriority(Category), nullptr),
7320 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007321 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007322
7323 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7324 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007325}
7326
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007327void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007328 IdentifierInfo *ClassName,
7329 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007330 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007331
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007332 // Find the corresponding interface. If we couldn't find the interface, the
7333 // program itself is ill-formed. However, we'll try to be helpful still by
7334 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00007335 NamedDecl *CurClass =
7336 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007337 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
7338 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007339 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007340
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007341 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007342 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007343 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007344
7345 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007346 // declarations in this class and any of its superclasses, except for
7347 // already-implemented categories in the class itself.
7348 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7349 Results.EnterNewScope();
7350 bool IgnoreImplemented = true;
7351 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007352 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007353 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007354 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007355 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7356 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007357 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007358
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007359 Class = Class->getSuperClass();
7360 IgnoreImplemented = false;
7361 }
7362 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007363
7364 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7365 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007366}
Douglas Gregor5d649882009-11-18 22:32:06 +00007367
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007368void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007369 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007370 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007371 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007372
7373 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007374 ObjCContainerDecl *Container =
7375 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7376 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7377 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007378 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007379
7380 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007381 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007382 for (const auto *D : Container->decls())
7383 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007384 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007385
Douglas Gregor5d649882009-11-18 22:32:06 +00007386 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007387 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007388 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007389 if (ObjCImplementationDecl *ClassImpl =
7390 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007391 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007392 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007393 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007394 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007395 AddObjCProperties(CCContext,
7396 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007397 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007398 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007399 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007400
7401 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7402 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007403}
7404
Fangrui Song050229d2018-11-24 00:14:31 +00007405void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7406 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007407 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007408 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007409 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007410 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007411
7412 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007413 ObjCContainerDecl *Container =
7414 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7415 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7416 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007417 return;
7418
Douglas Gregor5d649882009-11-18 22:32:06 +00007419 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007420 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007421 if (ObjCImplementationDecl *ClassImpl =
7422 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007423 Class = ClassImpl->getClassInterface();
7424 else
Fangrui Song050229d2018-11-24 00:14:31 +00007425 Class = cast<ObjCCategoryImplDecl>(Container)
7426 ->getCategoryDecl()
7427 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007428
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007429 // Determine the type of the property we're synthesizing.
7430 QualType PropertyType = Context.getObjCIdType();
7431 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007432 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7433 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007434 PropertyType =
7435 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007436
7437 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007438 Results.setPreferredType(PropertyType);
7439 }
7440 }
7441
Douglas Gregor5d649882009-11-18 22:32:06 +00007442 // Add all of the instance variables in this class and its superclasses.
7443 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007444 bool SawSimilarlyNamedIvar = false;
7445 std::string NameWithPrefix;
7446 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007447 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007448 std::string NameWithSuffix = PropertyName->getName().str();
7449 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007450 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007451 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007452 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007453 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7454 CurContext, nullptr, false);
7455
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007456 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007457 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007458 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007459 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007460 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007461 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007462
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007463 // Reduce the priority of this result by one, to give it a slight
7464 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007465 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007466 Results.data()[Results.size() - 1].Kind ==
7467 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007468 Results.data()[Results.size() - 1].Declaration == Ivar)
7469 Results.data()[Results.size() - 1].Priority--;
7470 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007471 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007472 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007473
Douglas Gregor331faa02011-04-18 14:13:53 +00007474 if (!SawSimilarlyNamedIvar) {
7475 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007476 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007477 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007478 typedef CodeCompletionResult Result;
7479 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007480 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007481 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007482
Douglas Gregor75acd922011-09-27 23:30:47 +00007483 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007484 Builder.AddResultTypeChunk(
7485 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007486 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007487 Results.AddResult(
7488 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007489 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007490
Douglas Gregor5d649882009-11-18 22:32:06 +00007491 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007492
7493 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7494 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007495}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007496
Douglas Gregor416b5752010-08-25 01:08:01 +00007497// Mapping from selectors to the methods that implement that selector, along
7498// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007499typedef llvm::DenseMap<Selector,
7500 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7501 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007502
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007503/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007504/// (and its superclasses, protocols, etc.) that meet the given
7505/// criteria. Insert those methods into the map of known methods,
7506/// indexed by selector so they can be easily found.
7507static void FindImplementableMethods(ASTContext &Context,
7508 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007509 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007510 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007511 KnownMethodsMap &KnownMethods,
7512 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007513 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007514 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007515 if (!IFace->hasDefinition())
7516 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007517
7518 IFace = IFace->getDefinition();
7519 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007520
Fangrui Song050229d2018-11-24 00:14:31 +00007521 const ObjCList<ObjCProtocolDecl> &Protocols =
7522 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007523 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007524 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007525 I != E; ++I)
7526 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007527 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007528
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007529 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007530 for (auto *Cat : IFace->visible_categories()) {
7531 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007532 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007533 }
7534
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007535 // Visit the superclass.
7536 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007537 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007538 WantInstanceMethods, ReturnType, KnownMethods,
7539 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007540 }
7541
7542 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7543 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007544 const ObjCList<ObjCProtocolDecl> &Protocols =
7545 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007546 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007547 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007548 I != E; ++I)
7549 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007550 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007551
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007552 // If this category is the original class, jump to the interface.
7553 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007554 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007555 WantInstanceMethods, ReturnType, KnownMethods,
7556 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007557 }
7558
7559 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007560 // Make sure we have a definition; that's what we'll walk.
7561 if (!Protocol->hasDefinition())
7562 return;
7563 Protocol = Protocol->getDefinition();
7564 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007565
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007566 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007567 const ObjCList<ObjCProtocolDecl> &Protocols =
7568 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007569 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007570 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007571 I != E; ++I)
7572 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7573 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007574 }
7575
7576 // Add methods in this container. This operation occurs last because
7577 // we want the methods from this container to override any methods
7578 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007579 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007580 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007581 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007582 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007583 continue;
7584
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007585 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007586 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007587 }
7588 }
7589}
7590
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007591/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007592/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007593static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007594 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007595 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007596 CodeCompletionBuilder &Builder) {
7597 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007598 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007599 if (!Quals.empty())
7600 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007601 Builder.AddTextChunk(
7602 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007603 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7604}
7605
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007606/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007607/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007608static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007609 if (!Class)
7610 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007611
Douglas Gregor669a25a2011-02-17 00:22:45 +00007612 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7613 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007614
Douglas Gregor669a25a2011-02-17 00:22:45 +00007615 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7616}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007617
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007618/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007619/// Key-Value Observing (KVO).
7620static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7621 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007622 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007623 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007624 ResultBuilder &Results) {
7625 IdentifierInfo *PropName = Property->getIdentifier();
7626 if (!PropName || PropName->getLength() == 0)
7627 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007628
Douglas Gregor75acd922011-09-27 23:30:47 +00007629 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7630
Douglas Gregor669a25a2011-02-17 00:22:45 +00007631 // Builder that will create each code completion.
7632 typedef CodeCompletionResult Result;
7633 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007634 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007635
Douglas Gregor669a25a2011-02-17 00:22:45 +00007636 // The selector table.
7637 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007638
Douglas Gregor669a25a2011-02-17 00:22:45 +00007639 // The property name, copied into the code completion allocation region
7640 // on demand.
7641 struct KeyHolder {
7642 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007643 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007644 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007645
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007646 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007647 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007648
Douglas Gregor669a25a2011-02-17 00:22:45 +00007649 operator const char *() {
7650 if (CopiedKey)
7651 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007652
Douglas Gregor669a25a2011-02-17 00:22:45 +00007653 return CopiedKey = Allocator.CopyString(Key);
7654 }
7655 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007656
Douglas Gregor669a25a2011-02-17 00:22:45 +00007657 // The uppercased name of the property name.
Benjamin Krameradcd0262020-01-28 20:23:46 +01007658 std::string UpperKey = std::string(PropName->getName());
Douglas Gregor669a25a2011-02-17 00:22:45 +00007659 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007660 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007661
Fangrui Song050229d2018-11-24 00:14:31 +00007662 bool ReturnTypeMatchesProperty =
7663 ReturnType.isNull() ||
7664 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7665 Property->getType());
7666 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007667
Douglas Gregor669a25a2011-02-17 00:22:45 +00007668 // Add the normal accessor -(type)key.
7669 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007670 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007671 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7672 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007673 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7674 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007675
Douglas Gregor669a25a2011-02-17 00:22:45 +00007676 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007677 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007678 CXCursor_ObjCInstanceMethodDecl));
7679 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007680
Douglas Gregor669a25a2011-02-17 00:22:45 +00007681 // If we have an integral or boolean property (or the user has provided
7682 // an integral or boolean return type), add the accessor -(type)isKey.
7683 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007684 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007685 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007686 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7687 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007688 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007689 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007690 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7691 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007692 if (ReturnType.isNull()) {
7693 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7694 Builder.AddTextChunk("BOOL");
7695 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7696 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007697
Fangrui Song050229d2018-11-24 00:14:31 +00007698 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007699 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007700 CXCursor_ObjCInstanceMethodDecl));
7701 }
7702 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007703
Douglas Gregor669a25a2011-02-17 00:22:45 +00007704 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007705 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007706 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007707 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007708 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007709 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007710 if (ReturnType.isNull()) {
7711 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7712 Builder.AddTextChunk("void");
7713 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7714 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007715
Fangrui Song050229d2018-11-24 00:14:31 +00007716 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007717 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007718 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7719 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007720 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007721 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007722 CXCursor_ObjCInstanceMethodDecl));
7723 }
7724 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007725
Douglas Gregor669a25a2011-02-17 00:22:45 +00007726 // Indexed and unordered accessors
7727 unsigned IndexedGetterPriority = CCP_CodePattern;
7728 unsigned IndexedSetterPriority = CCP_CodePattern;
7729 unsigned UnorderedGetterPriority = CCP_CodePattern;
7730 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007731 if (const auto *ObjCPointer =
7732 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007733 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7734 // If this interface type is not provably derived from a known
7735 // collection, penalize the corresponding completions.
7736 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007737 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007738 if (!InheritsFromClassNamed(IFace, "NSArray"))
7739 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7740 }
7741
7742 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007743 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007744 if (!InheritsFromClassNamed(IFace, "NSSet"))
7745 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7746 }
7747 }
7748 } else {
7749 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7750 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7751 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7752 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7753 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007754
Douglas Gregor669a25a2011-02-17 00:22:45 +00007755 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007756 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007757 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007758 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007759 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007760 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7761 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007762 if (ReturnType.isNull()) {
7763 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7764 Builder.AddTextChunk("NSUInteger");
7765 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7766 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007767
Fangrui Song050229d2018-11-24 00:14:31 +00007768 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7769 Results.AddResult(
7770 Result(Builder.TakeString(),
7771 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7772 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007773 }
7774 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007775
Douglas Gregor669a25a2011-02-17 00:22:45 +00007776 // Indexed getters
7777 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7778 if (IsInstanceMethod &&
7779 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007780 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007781 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007782 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007783 if (ReturnType.isNull()) {
7784 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7785 Builder.AddTextChunk("id");
7786 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7787 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007788
Douglas Gregor669a25a2011-02-17 00:22:45 +00007789 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7790 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7791 Builder.AddTextChunk("NSUInteger");
7792 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7793 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007794 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007795 CXCursor_ObjCInstanceMethodDecl));
7796 }
7797 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007798
Douglas Gregor669a25a2011-02-17 00:22:45 +00007799 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7800 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007801 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007802 (ReturnType->isObjCObjectPointerType() &&
Simon Pilgrimbf039442020-01-11 16:01:46 +00007803 ReturnType->castAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7804 ReturnType->castAs<ObjCObjectPointerType>()
Fangrui Song050229d2018-11-24 00:14:31 +00007805 ->getInterfaceDecl()
7806 ->getName() == "NSArray"))) {
7807 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007808 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007809 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007810 if (ReturnType.isNull()) {
7811 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7812 Builder.AddTextChunk("NSArray *");
7813 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7814 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007815
Douglas Gregor669a25a2011-02-17 00:22:45 +00007816 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7817 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7818 Builder.AddTextChunk("NSIndexSet *");
7819 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7820 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007821 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007822 CXCursor_ObjCInstanceMethodDecl));
7823 }
7824 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007825
Douglas Gregor669a25a2011-02-17 00:22:45 +00007826 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7827 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007828 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007829 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7830 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007831
David Blaikie82e95a32014-11-19 07:49:47 +00007832 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007833 if (ReturnType.isNull()) {
7834 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7835 Builder.AddTextChunk("void");
7836 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7837 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007838
Douglas Gregor669a25a2011-02-17 00:22:45 +00007839 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7840 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7841 Builder.AddPlaceholderChunk("object-type");
7842 Builder.AddTextChunk(" **");
7843 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7844 Builder.AddTextChunk("buffer");
7845 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7846 Builder.AddTypedTextChunk("range:");
7847 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7848 Builder.AddTextChunk("NSRange");
7849 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7850 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007851 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007852 CXCursor_ObjCInstanceMethodDecl));
7853 }
7854 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007855
Douglas Gregor669a25a2011-02-17 00:22:45 +00007856 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007857
Douglas Gregor669a25a2011-02-17 00:22:45 +00007858 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7859 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007860 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007861 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7862 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007863
David Blaikie82e95a32014-11-19 07:49:47 +00007864 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007865 if (ReturnType.isNull()) {
7866 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7867 Builder.AddTextChunk("void");
7868 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7869 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007870
Douglas Gregor669a25a2011-02-17 00:22:45 +00007871 Builder.AddTypedTextChunk("insertObject:");
7872 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7873 Builder.AddPlaceholderChunk("object-type");
7874 Builder.AddTextChunk(" *");
7875 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7876 Builder.AddTextChunk("object");
7877 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7878 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7879 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7880 Builder.AddPlaceholderChunk("NSUInteger");
7881 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7882 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007883 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007884 CXCursor_ObjCInstanceMethodDecl));
7885 }
7886 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007887
Douglas Gregor669a25a2011-02-17 00:22:45 +00007888 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7889 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007890 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007891 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7892 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007893
David Blaikie82e95a32014-11-19 07:49:47 +00007894 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007895 if (ReturnType.isNull()) {
7896 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7897 Builder.AddTextChunk("void");
7898 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7899 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007900
Douglas Gregor669a25a2011-02-17 00:22:45 +00007901 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7902 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7903 Builder.AddTextChunk("NSArray *");
7904 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7905 Builder.AddTextChunk("array");
7906 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7907 Builder.AddTypedTextChunk("atIndexes:");
7908 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7909 Builder.AddPlaceholderChunk("NSIndexSet *");
7910 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7911 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007912 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007913 CXCursor_ObjCInstanceMethodDecl));
7914 }
7915 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007916
Douglas Gregor669a25a2011-02-17 00:22:45 +00007917 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7918 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007919 std::string SelectorName =
7920 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007921 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007922 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007923 if (ReturnType.isNull()) {
7924 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7925 Builder.AddTextChunk("void");
7926 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7927 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007928
Douglas Gregor669a25a2011-02-17 00:22:45 +00007929 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7930 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7931 Builder.AddTextChunk("NSUInteger");
7932 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7933 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007934 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007935 CXCursor_ObjCInstanceMethodDecl));
7936 }
7937 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007938
Douglas Gregor669a25a2011-02-17 00:22:45 +00007939 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7940 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007941 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007942 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007943 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007944 if (ReturnType.isNull()) {
7945 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7946 Builder.AddTextChunk("void");
7947 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7948 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007949
Douglas Gregor669a25a2011-02-17 00:22:45 +00007950 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7951 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7952 Builder.AddTextChunk("NSIndexSet *");
7953 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7954 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007955 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007956 CXCursor_ObjCInstanceMethodDecl));
7957 }
7958 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007959
Douglas Gregor669a25a2011-02-17 00:22:45 +00007960 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7961 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007962 std::string SelectorName =
7963 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7964 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7965 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007966
David Blaikie82e95a32014-11-19 07:49:47 +00007967 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007968 if (ReturnType.isNull()) {
7969 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7970 Builder.AddTextChunk("void");
7971 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7972 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007973
Douglas Gregor669a25a2011-02-17 00:22:45 +00007974 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7975 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7976 Builder.AddPlaceholderChunk("NSUInteger");
7977 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7978 Builder.AddTextChunk("index");
7979 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7980 Builder.AddTypedTextChunk("withObject:");
7981 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7982 Builder.AddTextChunk("id");
7983 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7984 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007985 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007986 CXCursor_ObjCInstanceMethodDecl));
7987 }
7988 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007989
Douglas Gregor669a25a2011-02-17 00:22:45 +00007990 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7991 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007992 std::string SelectorName1 =
7993 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007994 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007995 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7996 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007997
David Blaikie82e95a32014-11-19 07:49:47 +00007998 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007999 if (ReturnType.isNull()) {
8000 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8001 Builder.AddTextChunk("void");
8002 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8003 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008004
Douglas Gregor669a25a2011-02-17 00:22:45 +00008005 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
8006 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8007 Builder.AddPlaceholderChunk("NSIndexSet *");
8008 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8009 Builder.AddTextChunk("indexes");
8010 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8011 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
8012 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8013 Builder.AddTextChunk("NSArray *");
8014 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8015 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008016 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008017 CXCursor_ObjCInstanceMethodDecl));
8018 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008019 }
8020
Douglas Gregor669a25a2011-02-17 00:22:45 +00008021 // Unordered getters
8022 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008023 if (IsInstanceMethod &&
8024 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00008025 (ReturnType->isObjCObjectPointerType() &&
8026 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00008027 ReturnType->getAs<ObjCObjectPointerType>()
8028 ->getInterfaceDecl()
8029 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008030 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008031 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008032 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8033 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008034 if (ReturnType.isNull()) {
8035 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8036 Builder.AddTextChunk("NSEnumerator *");
8037 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8038 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008039
Douglas Gregor669a25a2011-02-17 00:22:45 +00008040 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008041 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00008042 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008043 }
8044 }
8045
8046 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008047 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00008048 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008049 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008050 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008051 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008052 if (ReturnType.isNull()) {
8053 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8054 Builder.AddPlaceholderChunk("object-type");
8055 Builder.AddTextChunk(" *");
8056 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8057 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008058
Douglas Gregor669a25a2011-02-17 00:22:45 +00008059 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8060 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8061 if (ReturnType.isNull()) {
8062 Builder.AddPlaceholderChunk("object-type");
8063 Builder.AddTextChunk(" *");
8064 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00008065 Builder.AddTextChunk(GetCompletionTypeString(
8066 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008067 }
8068 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8069 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008070 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008071 CXCursor_ObjCInstanceMethodDecl));
8072 }
8073 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008074
Douglas Gregor669a25a2011-02-17 00:22:45 +00008075 // Mutable unordered accessors
8076 // - (void)addKeyObject:(type *)object
8077 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00008078 std::string SelectorName =
8079 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008080 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008081 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008082 if (ReturnType.isNull()) {
8083 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8084 Builder.AddTextChunk("void");
8085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8086 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008087
Douglas Gregor669a25a2011-02-17 00:22:45 +00008088 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8089 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8090 Builder.AddPlaceholderChunk("object-type");
8091 Builder.AddTextChunk(" *");
8092 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8093 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008094 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008095 CXCursor_ObjCInstanceMethodDecl));
8096 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008097 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008098
8099 // - (void)addKey:(NSSet *)objects
8100 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008101 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008102 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008103 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008104 if (ReturnType.isNull()) {
8105 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8106 Builder.AddTextChunk("void");
8107 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8108 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008109
Douglas Gregor669a25a2011-02-17 00:22:45 +00008110 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8111 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8112 Builder.AddTextChunk("NSSet *");
8113 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8114 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008115 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008116 CXCursor_ObjCInstanceMethodDecl));
8117 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008118 }
8119
Douglas Gregor669a25a2011-02-17 00:22:45 +00008120 // - (void)removeKeyObject:(type *)object
8121 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00008122 std::string SelectorName =
8123 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008124 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008125 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008126 if (ReturnType.isNull()) {
8127 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8128 Builder.AddTextChunk("void");
8129 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8130 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008131
Douglas Gregor669a25a2011-02-17 00:22:45 +00008132 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8133 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8134 Builder.AddPlaceholderChunk("object-type");
8135 Builder.AddTextChunk(" *");
8136 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8137 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008138 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008139 CXCursor_ObjCInstanceMethodDecl));
8140 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008141 }
8142
Douglas Gregor669a25a2011-02-17 00:22:45 +00008143 // - (void)removeKey:(NSSet *)objects
8144 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008145 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008146 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008147 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008148 if (ReturnType.isNull()) {
8149 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8150 Builder.AddTextChunk("void");
8151 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8152 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008153
Douglas Gregor669a25a2011-02-17 00:22:45 +00008154 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8155 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8156 Builder.AddTextChunk("NSSet *");
8157 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8158 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008159 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008160 CXCursor_ObjCInstanceMethodDecl));
8161 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008162 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008163
8164 // - (void)intersectKey:(NSSet *)objects
8165 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008166 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008167 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008168 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008169 if (ReturnType.isNull()) {
8170 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8171 Builder.AddTextChunk("void");
8172 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8173 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008174
Douglas Gregor669a25a2011-02-17 00:22:45 +00008175 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8176 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8177 Builder.AddTextChunk("NSSet *");
8178 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8179 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008180 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008181 CXCursor_ObjCInstanceMethodDecl));
8182 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008183 }
8184
Douglas Gregor669a25a2011-02-17 00:22:45 +00008185 // Key-Value Observing
8186 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008187 if (!IsInstanceMethod &&
8188 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00008189 (ReturnType->isObjCObjectPointerType() &&
Simon Pilgrimbf039442020-01-11 16:01:46 +00008190 ReturnType->castAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
8191 ReturnType->castAs<ObjCObjectPointerType>()
Fangrui Song050229d2018-11-24 00:14:31 +00008192 ->getInterfaceDecl()
8193 ->getName() == "NSSet"))) {
8194 std::string SelectorName =
8195 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008196 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008197 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8198 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008199 if (ReturnType.isNull()) {
8200 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00008201 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00008202 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8203 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008204
Douglas Gregor669a25a2011-02-17 00:22:45 +00008205 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008206 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008207 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00008208 }
8209 }
8210
8211 // + (BOOL)automaticallyNotifiesObserversForKey
8212 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00008213 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00008214 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00008215 std::string SelectorName =
8216 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00008217 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008218 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8219 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00008220 if (ReturnType.isNull()) {
8221 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8222 Builder.AddTextChunk("BOOL");
8223 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8224 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008225
Douglas Gregor857bcda2011-06-02 04:02:27 +00008226 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008227 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008228 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008229 }
8230 }
8231}
8232
Alex Lorenzb8740422017-10-24 16:39:37 +00008233void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008234 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008235 // Determine the return type of the method we're declaring, if
8236 // provided.
8237 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00008238 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008239 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00008240 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
8241 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008242 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008243 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00008244 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00008245 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00008246 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008247 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
8248 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008249 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00008250 } else if (ObjCCategoryImplDecl *CatImpl =
8251 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008252 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008253 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008254 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00008255 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008256 }
8257
8258 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00008259 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00008260 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008261 }
8262
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008263 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008264 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008265 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008266 return;
8267 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008268
Douglas Gregor636a61e2010-04-07 00:21:17 +00008269 // Find all of the methods that we could declare/implement here.
8270 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00008271 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
8272 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008273
Douglas Gregor636a61e2010-04-07 00:21:17 +00008274 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00008275 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008276 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008277 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008278 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008279 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00008280 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008281 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008282 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008283 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008284 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008285 CodeCompletionBuilder Builder(Results.getAllocator(),
8286 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00008287
8288 // Add the '-'/'+' prefix if it wasn't provided yet.
8289 if (!IsInstanceMethod) {
8290 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
8291 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8292 }
8293
Douglas Gregor636a61e2010-04-07 00:21:17 +00008294 // If the result type was not already provided, add it to the
8295 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008296 if (ReturnType.isNull()) {
8297 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
8298 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00008299 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
8300 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008301 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008302
8303 Selector Sel = Method->getSelector();
8304
8305 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00008306 Builder.AddTypedTextChunk(
8307 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008308
8309 // Add parameters to the pattern.
8310 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008311 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008312 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008313 P != PEnd; (void)++P, ++I) {
8314 // Add the part of the selector name.
8315 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008316 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00008317 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008318 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8319 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00008320 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008321 } else
8322 break;
8323
8324 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00008325 QualType ParamType;
8326 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
8327 ParamType = (*P)->getType();
8328 else
8329 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00008330 ParamType = ParamType.substObjCTypeArgs(
8331 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008332 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00008333 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
8334 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008335
Douglas Gregor636a61e2010-04-07 00:21:17 +00008336 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00008337 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008338 }
8339
8340 if (Method->isVariadic()) {
8341 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008342 Builder.AddChunk(CodeCompletionString::CK_Comma);
8343 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008344 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008345
Douglas Gregord37c59d2010-05-28 00:57:46 +00008346 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008347 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8349 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8350 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008351 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008352 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008353 Builder.AddTextChunk("return");
8354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8355 Builder.AddPlaceholderChunk("expression");
8356 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008357 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008358 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008359
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008360 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8361 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008362 }
8363
Douglas Gregor416b5752010-08-25 01:08:01 +00008364 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008365 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008366 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008367 setInBaseClass(R);
8368 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008369 }
8370
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008371 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008372 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008373 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008374 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008375 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008376
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008377 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008378 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008379 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008380 M != MEnd; ++M)
8381 KnownSelectors.insert(M->first);
8382
Douglas Gregor669a25a2011-02-17 00:22:45 +00008383 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8384 if (!IFace)
8385 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8386 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008387
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008388 if (IFace)
8389 for (auto *Cat : IFace->visible_categories())
8390 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008391
8392 if (IsInstanceMethod) {
8393 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8394 for (auto *P : Containers[I]->instance_properties())
8395 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8396 KnownSelectors, Results);
8397 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008398 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008399
Douglas Gregor636a61e2010-04-07 00:21:17 +00008400 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008401
8402 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8403 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008404}
Douglas Gregor95887f92010-07-08 23:20:03 +00008405
Fangrui Song050229d2018-11-24 00:14:31 +00008406void Sema::CodeCompleteObjCMethodDeclSelector(
8407 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8408 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008409 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008410 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008411 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008412 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8413 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008414 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008415 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008416 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008417
8418 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008419 }
8420 }
8421
8422 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008423 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008424 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008425 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008426 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008427
Douglas Gregor95887f92010-07-08 23:20:03 +00008428 if (ReturnTy)
8429 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008430
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008431 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008432 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8433 MEnd = MethodPool.end();
8434 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008435 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8436 : &M->second.second;
8437 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008438 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008439 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008440
Douglas Gregor45879692010-07-08 23:37:41 +00008441 if (AtParameterName) {
8442 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008443 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008444 if (NumSelIdents &&
8445 NumSelIdents <= MethList->getMethod()->param_size()) {
8446 ParmVarDecl *Param =
8447 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008448 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008449 CodeCompletionBuilder Builder(Results.getAllocator(),
8450 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008451 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008452 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008453 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008454 }
8455 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008456
Douglas Gregor45879692010-07-08 23:37:41 +00008457 continue;
8458 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008459
Nico Weber2e0c8f72014-12-27 03:58:08 +00008460 Result R(MethList->getMethod(),
8461 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008462 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008463 R.AllParametersAreInformative = false;
8464 R.DeclaringEntity = true;
8465 Results.MaybeAddResult(R, CurContext);
8466 }
8467 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008468
Douglas Gregor95887f92010-07-08 23:20:03 +00008469 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008470
8471 if (!AtParameterName && !SelIdents.empty() &&
8472 SelIdents.front()->getName().startswith("init")) {
8473 for (const auto &M : PP.macros()) {
8474 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8475 continue;
8476 Results.EnterNewScope();
8477 CodeCompletionBuilder Builder(Results.getAllocator(),
8478 Results.getCodeCompletionTUInfo());
8479 Builder.AddTypedTextChunk(
8480 Builder.getAllocator().CopyString(M.first->getName()));
8481 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8482 CXCursor_MacroDefinition));
8483 Results.ExitScope();
8484 }
8485 }
8486
Eric Liuf5ba09f2018-07-04 10:01:18 +00008487 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8488 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008489}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008490
Douglas Gregorec00a262010-08-24 22:20:20 +00008491void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008492 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008493 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008494 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008495 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008496
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008497 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008498 CodeCompletionBuilder Builder(Results.getAllocator(),
8499 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008500 Builder.AddTypedTextChunk("if");
8501 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8502 Builder.AddPlaceholderChunk("condition");
8503 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008504
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008505 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008506 Builder.AddTypedTextChunk("ifdef");
8507 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8508 Builder.AddPlaceholderChunk("macro");
8509 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008510
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008511 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008512 Builder.AddTypedTextChunk("ifndef");
8513 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8514 Builder.AddPlaceholderChunk("macro");
8515 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008516
8517 if (InConditional) {
8518 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008519 Builder.AddTypedTextChunk("elif");
8520 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8521 Builder.AddPlaceholderChunk("condition");
8522 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008523
8524 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008525 Builder.AddTypedTextChunk("else");
8526 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008527
8528 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008529 Builder.AddTypedTextChunk("endif");
8530 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008531 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008532
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008533 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008534 Builder.AddTypedTextChunk("include");
8535 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8536 Builder.AddTextChunk("\"");
8537 Builder.AddPlaceholderChunk("header");
8538 Builder.AddTextChunk("\"");
8539 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008540
8541 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008542 Builder.AddTypedTextChunk("include");
8543 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8544 Builder.AddTextChunk("<");
8545 Builder.AddPlaceholderChunk("header");
8546 Builder.AddTextChunk(">");
8547 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008548
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008549 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008550 Builder.AddTypedTextChunk("define");
8551 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8552 Builder.AddPlaceholderChunk("macro");
8553 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008554
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008555 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008556 Builder.AddTypedTextChunk("define");
8557 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8558 Builder.AddPlaceholderChunk("macro");
8559 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8560 Builder.AddPlaceholderChunk("args");
8561 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8562 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008563
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008564 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008565 Builder.AddTypedTextChunk("undef");
8566 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8567 Builder.AddPlaceholderChunk("macro");
8568 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008569
8570 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008571 Builder.AddTypedTextChunk("line");
8572 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8573 Builder.AddPlaceholderChunk("number");
8574 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008575
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008576 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008577 Builder.AddTypedTextChunk("line");
8578 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8579 Builder.AddPlaceholderChunk("number");
8580 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8581 Builder.AddTextChunk("\"");
8582 Builder.AddPlaceholderChunk("filename");
8583 Builder.AddTextChunk("\"");
8584 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008585
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008586 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008587 Builder.AddTypedTextChunk("error");
8588 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8589 Builder.AddPlaceholderChunk("message");
8590 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008591
8592 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008593 Builder.AddTypedTextChunk("pragma");
8594 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8595 Builder.AddPlaceholderChunk("arguments");
8596 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008597
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008598 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008599 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008600 Builder.AddTypedTextChunk("import");
8601 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8602 Builder.AddTextChunk("\"");
8603 Builder.AddPlaceholderChunk("header");
8604 Builder.AddTextChunk("\"");
8605 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008606
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008607 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008608 Builder.AddTypedTextChunk("import");
8609 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8610 Builder.AddTextChunk("<");
8611 Builder.AddPlaceholderChunk("header");
8612 Builder.AddTextChunk(">");
8613 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008614 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008615
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008616 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008617 Builder.AddTypedTextChunk("include_next");
8618 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8619 Builder.AddTextChunk("\"");
8620 Builder.AddPlaceholderChunk("header");
8621 Builder.AddTextChunk("\"");
8622 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008623
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008624 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008625 Builder.AddTypedTextChunk("include_next");
8626 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8627 Builder.AddTextChunk("<");
8628 Builder.AddPlaceholderChunk("header");
8629 Builder.AddTextChunk(">");
8630 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008631
8632 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008633 Builder.AddTypedTextChunk("warning");
8634 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8635 Builder.AddPlaceholderChunk("message");
8636 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008637
8638 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8639 // completions for them. And __include_macros is a Clang-internal extension
8640 // that we don't want to encourage anyone to use.
8641
8642 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8643 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008644
8645 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008646 Results.data(), Results.size());
8647}
8648
8649void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008650 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8651 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008652}
8653
Douglas Gregorec00a262010-08-24 22:20:20 +00008654void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008655 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008656 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008657 IsDefinition ? CodeCompletionContext::CCC_MacroName
8658 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008659 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008660 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008661 CodeCompletionBuilder Builder(Results.getAllocator(),
8662 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008663 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008664 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008665 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008666 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008667 Builder.AddTypedTextChunk(
8668 Builder.getAllocator().CopyString(M->first->getName()));
8669 Results.AddResult(CodeCompletionResult(
8670 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008671 }
8672 Results.ExitScope();
8673 } else if (IsDefinition) {
8674 // FIXME: Can we detect when the user just wrote an include guard above?
8675 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008676
Douglas Gregor0ac41382010-09-23 23:01:17 +00008677 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008678 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008679}
8680
Douglas Gregorec00a262010-08-24 22:20:20 +00008681void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008682 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008683 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008684 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008685
Douglas Gregorec00a262010-08-24 22:20:20 +00008686 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008687 AddMacroResults(PP, Results,
Sam McCall36082e32019-07-18 07:17:49 +00008688 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008689
Fangrui Song050229d2018-11-24 00:14:31 +00008690 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008691 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008692 CodeCompletionBuilder Builder(Results.getAllocator(),
8693 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008694 Builder.AddTypedTextChunk("defined");
8695 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8696 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8697 Builder.AddPlaceholderChunk("macro");
8698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8699 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008700 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008701
8702 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8703 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008704}
8705
8706void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8707 IdentifierInfo *Macro,
8708 MacroInfo *MacroInfo,
8709 unsigned Argument) {
8710 // FIXME: In the future, we could provide "overload" results, much like we
8711 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008712
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008713 // Now just ignore this. There will be another code-completion callback
8714 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008715}
8716
Sam McCall3d8051a2018-09-18 08:40:41 +00008717// This handles completion inside an #include filename, e.g. #include <foo/ba
8718// We look for the directory "foo" under each directory on the include path,
8719// list its files, and reassemble the appropriate #include.
8720void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8721 // RelDir should use /, but unescaped \ is possible on windows!
8722 // Our completions will normalize to / for simplicity, this case is rare.
8723 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8724 // We need the native slashes for the actual file system interactions.
8725 SmallString<128> NativeRelDir = StringRef(RelDir);
8726 llvm::sys::path::native(NativeRelDir);
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008727 llvm::vfs::FileSystem &FS =
8728 getSourceManager().getFileManager().getVirtualFileSystem();
Sam McCall3d8051a2018-09-18 08:40:41 +00008729
8730 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8731 CodeCompleter->getCodeCompletionTUInfo(),
8732 CodeCompletionContext::CCC_IncludedFile);
8733 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8734
8735 // Helper: adds one file or directory completion result.
8736 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8737 SmallString<64> TypedChunk = Filename;
8738 // Directory completion is up to the slash, e.g. <sys/
8739 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8740 auto R = SeenResults.insert(TypedChunk);
8741 if (R.second) { // New completion
8742 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8743 *R.first = InternedTyped; // Avoid dangling StringRef.
8744 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8745 CodeCompleter->getCodeCompletionTUInfo());
8746 Builder.AddTypedTextChunk(InternedTyped);
8747 // The result is a "Pattern", which is pretty opaque.
8748 // We may want to include the real filename to allow smart ranking.
8749 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8750 }
8751 };
8752
8753 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008754 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8755 bool IsSystem,
8756 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008757 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008758 if (!NativeRelDir.empty()) {
8759 if (LookupType == DirectoryLookup::LT_Framework) {
8760 // For a framework dir, #include <Foo/Bar/> actually maps to
8761 // a path of Foo.framework/Headers/Bar/.
8762 auto Begin = llvm::sys::path::begin(NativeRelDir);
8763 auto End = llvm::sys::path::end(NativeRelDir);
8764
8765 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8766 llvm::sys::path::append(Dir, ++Begin, End);
8767 } else {
8768 llvm::sys::path::append(Dir, NativeRelDir);
8769 }
8770 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008771
8772 std::error_code EC;
8773 unsigned Count = 0;
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008774 for (auto It = FS.dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008775 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008776 if (++Count == 2500) // If we happen to hit a huge directory,
8777 break; // bail out early so we're not too slow.
8778 StringRef Filename = llvm::sys::path::filename(It->path());
8779 switch (It->type()) {
8780 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008781 // All entries in a framework directory must have a ".framework" suffix,
8782 // but the suffix does not appear in the source code's include/import.
8783 if (LookupType == DirectoryLookup::LT_Framework &&
8784 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8785 break;
8786
Sam McCall3d8051a2018-09-18 08:40:41 +00008787 AddCompletion(Filename, /*IsDirectory=*/true);
8788 break;
8789 case llvm::sys::fs::file_type::regular_file:
8790 // Only files that really look like headers. (Except in system dirs).
8791 if (!IsSystem) {
8792 // Header extensions from Types.def, which we can't depend on here.
8793 if (!(Filename.endswith_lower(".h") ||
8794 Filename.endswith_lower(".hh") ||
8795 Filename.endswith_lower(".hpp") ||
8796 Filename.endswith_lower(".inc")))
8797 break;
8798 }
8799 AddCompletion(Filename, /*IsDirectory=*/false);
8800 break;
8801 default:
8802 break;
8803 }
8804 }
8805 };
8806
8807 // Helper: adds results relative to IncludeDir, if possible.
8808 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8809 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008810 switch (IncludeDir.getLookupType()) {
8811 case DirectoryLookup::LT_HeaderMap:
8812 // header maps are not (currently) enumerable.
8813 break;
8814 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008815 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8816 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008817 break;
8818 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008819 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8820 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008821 break;
8822 }
8823 };
8824
8825 // Finally with all our helpers, we can scan the include path.
8826 // Do this in standard order so deduplication keeps the right file.
8827 // (In case we decide to add more details to the results later).
8828 const auto &S = PP.getHeaderSearchInfo();
8829 using llvm::make_range;
8830 if (!Angled) {
8831 // The current directory is on the include path for "quoted" includes.
8832 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8833 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008834 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8835 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008836 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8837 AddFilesFromDirLookup(D, false);
8838 }
8839 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008840 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008841 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8842 AddFilesFromDirLookup(D, true);
8843
8844 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8845 Results.data(), Results.size());
8846}
8847
Douglas Gregor11583702010-08-25 17:04:25 +00008848void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008849 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008850 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8851 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008852}
8853
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008854void Sema::CodeCompleteAvailabilityPlatformName() {
8855 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8856 CodeCompleter->getCodeCompletionTUInfo(),
8857 CodeCompletionContext::CCC_Other);
8858 Results.EnterNewScope();
8859 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8860 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8861 Results.AddResult(CodeCompletionResult(Platform));
8862 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8863 Twine(Platform) + "ApplicationExtension")));
8864 }
8865 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008866 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8867 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008868}
8869
Fangrui Song050229d2018-11-24 00:14:31 +00008870void Sema::GatherGlobalCodeCompletions(
8871 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8872 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008873 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8874 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008875 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008876 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008877 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008878 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8879 Consumer,
8880 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008881 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008882
Douglas Gregorb14904c2010-08-13 22:48:40 +00008883 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008884 AddMacroResults(PP, Builder,
Sam McCall36082e32019-07-18 07:17:49 +00008885 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008886
Douglas Gregorb14904c2010-08-13 22:48:40 +00008887 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008888 Results.insert(Results.end(), Builder.data(),
8889 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008890}