blob: cebf97a09abab863475878d156b90a5a238e828a [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"
Douglas Gregorf2510672009-09-21 19:57:38 +000016#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000017#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000018#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000019#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000020#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000021#include "clang/Lex/MacroInfo.h"
22#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Overload.h"
26#include "clang/Sema/Scope.h"
27#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000028#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000029#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000030#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000031#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000032#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000033#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000034#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000035#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000036#include "llvm/ADT/iterator_range.h"
37#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000038#include <list>
39#include <map>
40#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000041
42using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000043using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000044
Douglas Gregor3545ff42009-09-21 16:56:56 +000045namespace {
Fangrui Song050229d2018-11-24 00:14:31 +000046/// A container of code-completion results.
47class ResultBuilder {
48public:
49 /// The type of a name-lookup filter, which can be provided to the
50 /// name-lookup routines to specify which declarations should be included in
51 /// the result set (when it returns true) and which declarations should be
52 /// filtered out (returns false).
53 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000054
Fangrui Song050229d2018-11-24 00:14:31 +000055 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000056
Fangrui Song050229d2018-11-24 00:14:31 +000057private:
58 /// The actual results we have found.
59 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000060
Fangrui Song050229d2018-11-24 00:14:31 +000061 /// A record of all of the declarations we have found and placed
62 /// into the result set, used to ensure that no declaration ever gets into
63 /// the result set twice.
64 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000065
Fangrui Song050229d2018-11-24 00:14:31 +000066 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000067
Fangrui Song050229d2018-11-24 00:14:31 +000068 /// An entry in the shadow map, which is optimized to store
69 /// a single (declaration, index) mapping (the common case) but
70 /// can also store a list of (declaration, index) mappings.
71 class ShadowMapEntry {
72 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000073
Fangrui Song050229d2018-11-24 00:14:31 +000074 /// Contains either the solitary NamedDecl * or a vector
75 /// of (declaration, index) pairs.
76 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000077
Fangrui Song050229d2018-11-24 00:14:31 +000078 /// When the entry contains a single declaration, this is
79 /// the index associated with that entry.
80 unsigned SingleDeclIndex;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000081
Douglas Gregor3545ff42009-09-21 16:56:56 +000082 public:
Fangrui Song050229d2018-11-24 00:14:31 +000083 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000084
Fangrui Song050229d2018-11-24 00:14:31 +000085 void Add(const NamedDecl *ND, unsigned Index) {
86 if (DeclOrVector.isNull()) {
87 // 0 - > 1 elements: just set the single element information.
88 DeclOrVector = ND;
89 SingleDeclIndex = Index;
90 return;
91 }
92
93 if (const NamedDecl *PrevND =
94 DeclOrVector.dyn_cast<const NamedDecl *>()) {
95 // 1 -> 2 elements: create the vector of results and push in the
96 // existing declaration.
97 DeclIndexPairVector *Vec = new DeclIndexPairVector;
98 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
99 DeclOrVector = Vec;
100 }
101
102 // Add the new element to the end of the vector.
103 DeclOrVector.get<DeclIndexPairVector *>()->push_back(
104 DeclIndexPair(ND, Index));
105 }
106
107 void Destroy() {
108 if (DeclIndexPairVector *Vec =
109 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
110 delete Vec;
111 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05fcf842010-11-02 20:36:02 +0000112 }
113 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000114
Fangrui Song050229d2018-11-24 00:14:31 +0000115 // Iteration.
116 class iterator;
117 iterator begin() const;
118 iterator end() const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000119 };
Fangrui Song050229d2018-11-24 00:14:31 +0000120
121 /// A mapping from declaration names to the declarations that have
122 /// this name within a particular scope and their index within the list of
123 /// results.
124 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
125
126 /// The semantic analysis object for which results are being
127 /// produced.
128 Sema &SemaRef;
129
130 /// The allocator used to allocate new code-completion strings.
131 CodeCompletionAllocator &Allocator;
132
133 CodeCompletionTUInfo &CCTUInfo;
134
135 /// If non-NULL, a filter function used to remove any code-completion
136 /// results that are not desirable.
137 LookupFilter Filter;
138
139 /// Whether we should allow declarations as
140 /// nested-name-specifiers that would otherwise be filtered out.
141 bool AllowNestedNameSpecifiers;
142
143 /// If set, the type that we would prefer our resulting value
144 /// declarations to have.
145 ///
146 /// Closely matching the preferred type gives a boost to a result's
147 /// priority.
148 CanQualType PreferredType;
149
150 /// A list of shadow maps, which is used to model name hiding at
151 /// different levels of, e.g., the inheritance hierarchy.
152 std::list<ShadowMap> ShadowMaps;
153
154 /// If we're potentially referring to a C++ member function, the set
155 /// of qualifiers applied to the object type.
156 Qualifiers ObjectTypeQualifiers;
157
158 /// Whether the \p ObjectTypeQualifiers field is active.
159 bool HasObjectTypeQualifiers;
160
161 /// The selector that we prefer.
162 Selector PreferredSelector;
163
164 /// The completion context in which we are gathering results.
165 CodeCompletionContext CompletionContext;
166
167 /// If we are in an instance method definition, the \@implementation
168 /// object.
169 ObjCImplementationDecl *ObjCImplementation;
170
171 void AdjustResultPriorityForDecl(Result &R);
172
173 void MaybeAddConstructorResults(Result R);
174
175public:
176 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
177 CodeCompletionTUInfo &CCTUInfo,
178 const CodeCompletionContext &CompletionContext,
179 LookupFilter Filter = nullptr)
180 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
181 Filter(Filter), AllowNestedNameSpecifiers(false),
182 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
183 ObjCImplementation(nullptr) {
184 // If this is an Objective-C instance method definition, dig out the
185 // corresponding implementation.
186 switch (CompletionContext.getKind()) {
187 case CodeCompletionContext::CCC_Expression:
188 case CodeCompletionContext::CCC_ObjCMessageReceiver:
189 case CodeCompletionContext::CCC_ParenthesizedExpression:
190 case CodeCompletionContext::CCC_Statement:
191 case CodeCompletionContext::CCC_Recovery:
192 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
193 if (Method->isInstanceMethod())
194 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
195 ObjCImplementation = Interface->getImplementation();
196 break;
197
198 default:
199 break;
200 }
201 }
202
203 /// Determine the priority for a reference to the given declaration.
204 unsigned getBasePriority(const NamedDecl *D);
205
206 /// Whether we should include code patterns in the completion
207 /// results.
208 bool includeCodePatterns() const {
209 return SemaRef.CodeCompleter &&
210 SemaRef.CodeCompleter->includeCodePatterns();
211 }
212
213 /// Set the filter used for code-completion results.
214 void setFilter(LookupFilter Filter) { this->Filter = Filter; }
215
216 Result *data() { return Results.empty() ? nullptr : &Results.front(); }
217 unsigned size() const { return Results.size(); }
218 bool empty() const { return Results.empty(); }
219
220 /// Specify the preferred type.
221 void setPreferredType(QualType T) {
222 PreferredType = SemaRef.Context.getCanonicalType(T);
223 }
224
225 /// Set the cv-qualifiers on the object type, for us in filtering
226 /// calls to member functions.
227 ///
228 /// When there are qualifiers in this set, they will be used to filter
229 /// out member functions that aren't available (because there will be a
230 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
231 /// match.
232 void setObjectTypeQualifiers(Qualifiers Quals) {
233 ObjectTypeQualifiers = Quals;
234 HasObjectTypeQualifiers = true;
235 }
236
237 /// Set the preferred selector.
238 ///
239 /// When an Objective-C method declaration result is added, and that
240 /// method's selector matches this preferred selector, we give that method
241 /// a slight priority boost.
242 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
243
244 /// Retrieve the code-completion context for which results are
245 /// being collected.
246 const CodeCompletionContext &getCompletionContext() const {
247 return CompletionContext;
248 }
249
250 /// Specify whether nested-name-specifiers are allowed.
251 void allowNestedNameSpecifiers(bool Allow = true) {
252 AllowNestedNameSpecifiers = Allow;
253 }
254
255 /// Return the semantic analysis object for which we are collecting
256 /// code completion results.
257 Sema &getSema() const { return SemaRef; }
258
259 /// Retrieve the allocator used to allocate code completion strings.
260 CodeCompletionAllocator &getAllocator() const { return Allocator; }
261
262 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
263
264 /// Determine whether the given declaration is at all interesting
265 /// as a code-completion result.
266 ///
267 /// \param ND the declaration that we are inspecting.
268 ///
269 /// \param AsNestedNameSpecifier will be set true if this declaration is
270 /// only interesting when it is a nested-name-specifier.
271 bool isInterestingDecl(const NamedDecl *ND,
272 bool &AsNestedNameSpecifier) const;
273
274 /// Check whether the result is hidden by the Hiding declaration.
275 ///
276 /// \returns true if the result is hidden and cannot be found, false if
277 /// the hidden result could still be found. When false, \p R may be
278 /// modified to describe how the result can be found (e.g., via extra
279 /// qualification).
280 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
281 const NamedDecl *Hiding);
282
283 /// Add a new result to this result set (if it isn't already in one
284 /// of the shadow maps), or replace an existing result (for, e.g., a
285 /// redeclaration).
286 ///
287 /// \param R the result to add (if it is unique).
288 ///
289 /// \param CurContext the context in which this result will be named.
290 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
291
292 /// Add a new result to this result set, where we already know
293 /// the hiding declaration (if any).
294 ///
295 /// \param R the result to add (if it is unique).
296 ///
297 /// \param CurContext the context in which this result will be named.
298 ///
299 /// \param Hiding the declaration that hides the result.
300 ///
301 /// \param InBaseClass whether the result was found in a base
302 /// class of the searched context.
303 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
304 bool InBaseClass);
305
306 /// Add a new non-declaration result to this result set.
307 void AddResult(Result R);
308
309 /// Enter into a new scope.
310 void EnterNewScope();
311
312 /// Exit from the current scope.
313 void ExitScope();
314
315 /// Ignore this declaration, if it is seen again.
316 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
317
318 /// Add a visited context.
319 void addVisitedContext(DeclContext *Ctx) {
320 CompletionContext.addVisitedContext(Ctx);
321 }
322
323 /// \name Name lookup predicates
324 ///
325 /// These predicates can be passed to the name lookup functions to filter the
326 /// results of name lookup. All of the predicates have the same type, so that
327 ///
328 //@{
329 bool IsOrdinaryName(const NamedDecl *ND) const;
330 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
331 bool IsIntegralConstantValue(const NamedDecl *ND) const;
332 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
333 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
334 bool IsEnum(const NamedDecl *ND) const;
335 bool IsClassOrStruct(const NamedDecl *ND) const;
336 bool IsUnion(const NamedDecl *ND) const;
337 bool IsNamespace(const NamedDecl *ND) const;
338 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
339 bool IsType(const NamedDecl *ND) const;
340 bool IsMember(const NamedDecl *ND) const;
341 bool IsObjCIvar(const NamedDecl *ND) const;
342 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
343 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
344 bool IsObjCCollection(const NamedDecl *ND) const;
345 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
346 //@}
347};
348} // namespace
Douglas Gregor3545ff42009-09-21 16:56:56 +0000349
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000350void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
351 if (isa<BlockDecl>(S.CurContext)) {
352 if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
353 Type = BSI->ReturnType;
354 ExpectedLoc = Tok;
355 }
356 } else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) {
357 Type = Function->getReturnType();
358 ExpectedLoc = Tok;
359 } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) {
360 Type = Method->getReturnType();
361 ExpectedLoc = Tok;
362 }
363}
364
365void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {
366 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
367 Type = VD ? VD->getType() : QualType();
368 ExpectedLoc = Tok;
369}
370
371void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,
372 SourceLocation LParLoc) {
373 // expected type for parenthesized expression does not change.
374 if (ExpectedLoc == LParLoc)
375 ExpectedLoc = Tok;
376}
377
378static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
379 tok::TokenKind Op) {
380 if (!LHS)
381 return QualType();
382
383 QualType LHSType = LHS->getType();
384 if (LHSType->isPointerType()) {
385 if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
386 return S.getASTContext().getPointerDiffType();
387 // Pointer difference is more common than subtracting an int from a pointer.
388 if (Op == tok::minus)
389 return LHSType;
390 }
391
392 switch (Op) {
393 // No way to infer the type of RHS from LHS.
394 case tok::comma:
395 return QualType();
396 // Prefer the type of the left operand for all of these.
397 // Arithmetic operations.
398 case tok::plus:
399 case tok::plusequal:
400 case tok::minus:
401 case tok::minusequal:
402 case tok::percent:
403 case tok::percentequal:
404 case tok::slash:
405 case tok::slashequal:
406 case tok::star:
407 case tok::starequal:
408 // Assignment.
409 case tok::equal:
410 // Comparison operators.
411 case tok::equalequal:
412 case tok::exclaimequal:
413 case tok::less:
414 case tok::lessequal:
415 case tok::greater:
416 case tok::greaterequal:
417 case tok::spaceship:
418 return LHS->getType();
419 // Binary shifts are often overloaded, so don't try to guess those.
420 case tok::greatergreater:
421 case tok::greatergreaterequal:
422 case tok::lessless:
423 case tok::lesslessequal:
424 if (LHSType->isIntegralOrEnumerationType())
425 return S.getASTContext().IntTy;
426 return QualType();
427 // Logical operators, assume we want bool.
428 case tok::ampamp:
429 case tok::pipepipe:
430 case tok::caretcaret:
431 return S.getASTContext().BoolTy;
432 // Operators often used for bit manipulation are typically used with the type
433 // of the left argument.
434 case tok::pipe:
435 case tok::pipeequal:
436 case tok::caret:
437 case tok::caretequal:
438 case tok::amp:
439 case tok::ampequal:
440 if (LHSType->isIntegralOrEnumerationType())
441 return LHSType;
442 return QualType();
443 // RHS should be a pointer to a member of the 'LHS' type, but we can't give
444 // any particular type here.
445 case tok::periodstar:
446 case tok::arrowstar:
447 return QualType();
448 default:
449 // FIXME(ibiryukov): handle the missing op, re-add the assertion.
450 // assert(false && "unhandled binary op");
451 return QualType();
452 }
453}
454
455/// Get preferred type for an argument of an unary expression. \p ContextType is
456/// preferred type of the whole unary expression.
457static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType,
458 tok::TokenKind Op) {
459 switch (Op) {
460 case tok::exclaim:
461 return S.getASTContext().BoolTy;
462 case tok::amp:
463 if (!ContextType.isNull() && ContextType->isPointerType())
464 return ContextType->getPointeeType();
465 return QualType();
466 case tok::star:
467 if (ContextType.isNull())
468 return QualType();
469 return S.getASTContext().getPointerType(ContextType.getNonReferenceType());
470 case tok::plus:
471 case tok::minus:
472 case tok::tilde:
473 case tok::minusminus:
474 case tok::plusplus:
475 if (ContextType.isNull())
476 return S.getASTContext().IntTy;
477 // leave as is, these operators typically return the same type.
478 return ContextType;
479 case tok::kw___real:
480 case tok::kw___imag:
481 return QualType();
482 default:
483 assert(false && "unhnalded unary op");
484 return QualType();
485 }
486}
487
488void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,
489 tok::TokenKind Op) {
490 Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);
491 ExpectedLoc = Tok;
492}
493
494void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok,
495 Expr *Base) {
496 if (!Base)
497 return;
498 Type = this->get(Base->getBeginLoc());
499 ExpectedLoc = Tok;
500}
501
502void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,
503 tok::TokenKind OpKind,
504 SourceLocation OpLoc) {
505 Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);
506 ExpectedLoc = Tok;
507}
508
509void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,
510 Expr *LHS) {
511 Type = S.getASTContext().IntTy;
512 ExpectedLoc = Tok;
513}
514
515void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,
516 QualType CastType) {
517 Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();
518 ExpectedLoc = Tok;
519}
520
521void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {
522 Type = S.getASTContext().BoolTy;
523 ExpectedLoc = Tok;
524}
525
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000526class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000527 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000528 unsigned SingleDeclIndex;
529
530public:
531 typedef DeclIndexPair value_type;
532 typedef value_type reference;
533 typedef std::ptrdiff_t difference_type;
534 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000535
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000536 class pointer {
537 DeclIndexPair Value;
538
539 public:
Fangrui Song050229d2018-11-24 00:14:31 +0000540 pointer(const DeclIndexPair &Value) : Value(Value) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000541
Fangrui Song050229d2018-11-24 00:14:31 +0000542 const DeclIndexPair *operator->() const { return &Value; }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000543 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000544
545 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000546
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000547 iterator(const NamedDecl *SingleDecl, unsigned Index)
Fangrui Song050229d2018-11-24 00:14:31 +0000548 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000549
550 iterator(const DeclIndexPair *Iterator)
Fangrui Song050229d2018-11-24 00:14:31 +0000551 : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000552
553 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000554 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000555 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000556 SingleDeclIndex = 0;
557 return *this;
558 }
559
Fangrui Song050229d2018-11-24 00:14:31 +0000560 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000561 ++I;
562 DeclOrIterator = I;
563 return *this;
564 }
565
Chris Lattner9795b392010-09-04 18:12:20 +0000566 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000567 iterator tmp(*this);
568 ++(*this);
569 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000570 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000571
572 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000573 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000574 return reference(ND, SingleDeclIndex);
575
Fangrui Song050229d2018-11-24 00:14:31 +0000576 return *DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000577 }
578
Fangrui Song050229d2018-11-24 00:14:31 +0000579 pointer operator->() const { return pointer(**this); }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000580
581 friend bool operator==(const iterator &X, const iterator &Y) {
Fangrui Song050229d2018-11-24 00:14:31 +0000582 return X.DeclOrIterator.getOpaqueValue() ==
583 Y.DeclOrIterator.getOpaqueValue() &&
584 X.SingleDeclIndex == Y.SingleDeclIndex;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000585 }
586
587 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000588 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000589 }
590};
591
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000592ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000593ResultBuilder::ShadowMapEntry::begin() const {
594 if (DeclOrVector.isNull())
595 return iterator();
596
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000597 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000598 return iterator(ND, SingleDeclIndex);
599
600 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
601}
602
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000603ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000604ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000605 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000606 return iterator();
607
608 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
609}
610
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000611/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000612/// (\p CurContext) to the target context (\p TargetContext).
613///
614/// \param Context the AST context in which the qualification will be used.
615///
616/// \param CurContext the context where an entity is being named, which is
617/// typically based on the current scope.
618///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000619/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000620/// resides.
621///
622/// \returns a nested name specifier that refers into the target context, or
623/// NULL if no qualification is needed.
624static NestedNameSpecifier *
Fangrui Song050229d2018-11-24 00:14:31 +0000625getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000626 const DeclContext *TargetContext) {
627 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000628
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000629 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000630 CommonAncestor && !CommonAncestor->Encloses(CurContext);
631 CommonAncestor = CommonAncestor->getLookupParent()) {
632 if (CommonAncestor->isTransparentContext() ||
633 CommonAncestor->isFunctionOrMethod())
634 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000635
Douglas Gregor2af2f672009-09-21 20:12:40 +0000636 TargetParents.push_back(CommonAncestor);
637 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000638
639 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000640 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000641 const DeclContext *Parent = TargetParents.pop_back_val();
642
Fangrui Song050229d2018-11-24 00:14:31 +0000643 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000644 if (!Namespace->getIdentifier())
645 continue;
646
Douglas Gregor2af2f672009-09-21 20:12:40 +0000647 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Fangrui Song050229d2018-11-24 00:14:31 +0000648 } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
649 Result = NestedNameSpecifier::Create(
650 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000651 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000652 return Result;
653}
654
Alp Toker034bbd52014-06-30 01:33:53 +0000655/// Determine whether \p Id is a name reserved for the implementation (C99
656/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000657static bool isReservedName(const IdentifierInfo *Id,
658 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000659 if (Id->getLength() < 2)
660 return false;
661 const char *Name = Id->getNameStart();
662 return Name[0] == '_' &&
Fangrui Song050229d2018-11-24 00:14:31 +0000663 (Name[1] == '_' ||
664 (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000665}
666
667// Some declarations have reserved names that we don't want to ever show.
668// Filter out names reserved for the implementation if they come from a
669// system header.
670static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
671 const IdentifierInfo *Id = ND->getIdentifier();
672 if (!Id)
673 return false;
674
675 // Ignore reserved names for compiler provided decls.
676 if (isReservedName(Id) && ND->getLocation().isInvalid())
677 return true;
678
679 // For system headers ignore only double-underscore names.
680 // This allows for system headers providing private symbols with a single
681 // underscore.
682 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000683 SemaRef.SourceMgr.isInSystemHeader(
684 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
685 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000686
687 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000688}
689
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000690bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000691 bool &AsNestedNameSpecifier) const {
692 AsNestedNameSpecifier = false;
693
Richard Smithf2005d32015-12-29 23:34:32 +0000694 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000695 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000696
697 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000698 if (!ND->getDeclName())
699 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000700
Douglas Gregor3545ff42009-09-21 16:56:56 +0000701 // Friend declarations and declarations introduced due to friends are never
702 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000703 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000704 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000705
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000706 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000707 if (isa<ClassTemplateSpecializationDecl>(ND) ||
708 isa<ClassTemplatePartialSpecializationDecl>(ND))
709 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000710
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000711 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000712 if (isa<UsingDecl>(ND))
713 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000714
715 if (shouldIgnoreDueToReservedName(ND, SemaRef))
716 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000717
Douglas Gregor59cab552010-08-16 23:05:20 +0000718 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000719 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
720 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000721 AsNestedNameSpecifier = true;
722
Douglas Gregor3545ff42009-09-21 16:56:56 +0000723 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000724 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000725 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000726 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000727 IsNestedNameSpecifier(ND) &&
728 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000729 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000730 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
731 AsNestedNameSpecifier = true;
732 return true;
733 }
734
Douglas Gregor7c208612010-01-14 00:20:49 +0000735 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000736 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000737 // ... then it must be interesting!
738 return true;
739}
740
Douglas Gregore0717ab2010-01-14 00:41:07 +0000741bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000742 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000743 // In C, there is no way to refer to a hidden name.
744 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
745 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000746 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000747 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000748
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000749 const DeclContext *HiddenCtx =
750 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000751
Douglas Gregore0717ab2010-01-14 00:41:07 +0000752 // There is no way to qualify a name declared in a function or method.
753 if (HiddenCtx->isFunctionOrMethod())
754 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000755
Sebastian Redl50c68252010-08-31 00:36:30 +0000756 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000757 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000758
Douglas Gregore0717ab2010-01-14 00:41:07 +0000759 // We can refer to the result with the appropriate qualification. Do it.
760 R.Hidden = true;
761 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000762
Douglas Gregore0717ab2010-01-14 00:41:07 +0000763 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000764 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000765 R.Declaration->getDeclContext());
766 return false;
767}
768
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000769/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000770/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000771SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000772 switch (T->getTypeClass()) {
773 case Type::Builtin:
774 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000775 case BuiltinType::Void:
776 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000777
Fangrui Song050229d2018-11-24 00:14:31 +0000778 case BuiltinType::NullPtr:
779 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000780
Fangrui Song050229d2018-11-24 00:14:31 +0000781 case BuiltinType::Overload:
782 case BuiltinType::Dependent:
783 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000784
Fangrui Song050229d2018-11-24 00:14:31 +0000785 case BuiltinType::ObjCId:
786 case BuiltinType::ObjCClass:
787 case BuiltinType::ObjCSel:
788 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000789
Fangrui Song050229d2018-11-24 00:14:31 +0000790 default:
791 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000792 }
David Blaikie8a40f702012-01-17 06:56:22 +0000793
Douglas Gregor95887f92010-07-08 23:20:03 +0000794 case Type::Complex:
795 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000796
Douglas Gregor95887f92010-07-08 23:20:03 +0000797 case Type::Pointer:
798 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000799
Douglas Gregor95887f92010-07-08 23:20:03 +0000800 case Type::BlockPointer:
801 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000802
Douglas Gregor95887f92010-07-08 23:20:03 +0000803 case Type::LValueReference:
804 case Type::RValueReference:
805 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000806
Douglas Gregor95887f92010-07-08 23:20:03 +0000807 case Type::ConstantArray:
808 case Type::IncompleteArray:
809 case Type::VariableArray:
810 case Type::DependentSizedArray:
811 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000812
Douglas Gregor95887f92010-07-08 23:20:03 +0000813 case Type::DependentSizedExtVector:
814 case Type::Vector:
815 case Type::ExtVector:
816 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000817
Douglas Gregor95887f92010-07-08 23:20:03 +0000818 case Type::FunctionProto:
819 case Type::FunctionNoProto:
820 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000821
Douglas Gregor95887f92010-07-08 23:20:03 +0000822 case Type::Record:
823 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000824
Douglas Gregor95887f92010-07-08 23:20:03 +0000825 case Type::Enum:
826 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000827
Douglas Gregor95887f92010-07-08 23:20:03 +0000828 case Type::ObjCObject:
829 case Type::ObjCInterface:
830 case Type::ObjCObjectPointer:
831 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000832
Douglas Gregor95887f92010-07-08 23:20:03 +0000833 default:
834 return STC_Other;
835 }
836}
837
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000838/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000839/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000840QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000841 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000842
Fangrui Song050229d2018-11-24 00:14:31 +0000843 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000844 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000845 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000846 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000847
Douglas Gregor95887f92010-07-08 23:20:03 +0000848 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000849 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000850 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000851 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000852 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000853 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000854 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000855 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000856 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000857 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000858 T = Value->getType();
Ilya Biryukovc514ade2019-01-24 10:41:43 +0000859
860 if (T.isNull())
Douglas Gregor95887f92010-07-08 23:20:03 +0000861 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000862
863 // Dig through references, function pointers, and block pointers to
864 // get down to the likely type of an expression when the entity is
865 // used.
866 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000867 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000868 T = Ref->getPointeeType();
869 continue;
870 }
871
Fangrui Song050229d2018-11-24 00:14:31 +0000872 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000873 if (Pointer->getPointeeType()->isFunctionType()) {
874 T = Pointer->getPointeeType();
875 continue;
876 }
877
878 break;
879 }
880
Fangrui Song050229d2018-11-24 00:14:31 +0000881 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000882 T = Block->getPointeeType();
883 continue;
884 }
885
Fangrui Song050229d2018-11-24 00:14:31 +0000886 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000887 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000888 continue;
889 }
890
891 break;
892 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000893
Douglas Gregoraf670a82011-04-14 20:33:34 +0000894 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000895}
896
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000897unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
898 if (!ND)
899 return CCP_Unlikely;
900
901 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000902 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
903 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000904 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000905 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000906 if (ImplicitParam->getIdentifier() &&
907 ImplicitParam->getIdentifier()->isStr("_cmd"))
908 return CCP_ObjC_cmd;
909
910 return CCP_LocalDeclaration;
911 }
Richard Smith541b38b2013-09-20 01:15:31 +0000912
913 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000914 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
915 // Explicit destructor calls are very rare.
916 if (isa<CXXDestructorDecl>(ND))
917 return CCP_Unlikely;
918 // Explicit operator and conversion function calls are also very rare.
919 auto DeclNameKind = ND->getDeclName().getNameKind();
920 if (DeclNameKind == DeclarationName::CXXOperatorName ||
921 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
922 DeclNameKind == DeclarationName::CXXConversionFunctionName)
923 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000924 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000925 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000926
927 // Content-based decisions.
928 if (isa<EnumConstantDecl>(ND))
929 return CCP_Constant;
930
Douglas Gregor52e0de42013-01-31 05:03:46 +0000931 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
932 // message receiver, or parenthesized expression context. There, it's as
933 // likely that the user will want to write a type as other declarations.
934 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
935 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000936 CompletionContext.getKind() ==
937 CodeCompletionContext::CCC_ObjCMessageReceiver ||
938 CompletionContext.getKind() ==
939 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000940 return CCP_Type;
941
942 return CCP_Declaration;
943}
944
Douglas Gregor50832e02010-09-20 22:39:41 +0000945void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
946 // If this is an Objective-C method declaration whose selector matches our
947 // preferred selector, give it a priority boost.
948 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000949 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000950 if (PreferredSelector == Method->getSelector())
951 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000952
Douglas Gregor50832e02010-09-20 22:39:41 +0000953 // If we have a preferred type, adjust the priority for results with exactly-
954 // matching or nearly-matching types.
955 if (!PreferredType.isNull()) {
956 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
957 if (!T.isNull()) {
958 CanQualType TC = SemaRef.Context.getCanonicalType(T);
959 // Check for exactly-matching types (modulo qualifiers).
960 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
961 R.Priority /= CCF_ExactTypeMatch;
962 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +0000963 else if ((getSimplifiedTypeClass(PreferredType) ==
964 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000965 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000966 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000967 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000968 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000969}
970
Benjamin Kramer756ecb82019-02-11 14:52:15 +0000971static DeclContext::lookup_result getConstructors(ASTContext &Context,
972 const CXXRecordDecl *Record) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +0000973 QualType RecordTy = Context.getTypeDeclType(Record);
974 DeclarationName ConstructorName =
975 Context.DeclarationNames.getCXXConstructorName(
976 Context.getCanonicalType(RecordTy));
977 return Record->lookup(ConstructorName);
978}
979
Douglas Gregor0212fd72010-09-21 16:06:22 +0000980void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000981 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000982 !CompletionContext.wantConstructorResults())
983 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000984
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000985 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000986 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000987 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000988 Record = ClassTemplate->getTemplatedDecl();
989 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
990 // Skip specializations and partial specializations.
991 if (isa<ClassTemplateSpecializationDecl>(Record))
992 return;
993 } else {
994 // There are no constructors here.
995 return;
996 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000997
Douglas Gregor0212fd72010-09-21 16:06:22 +0000998 Record = Record->getDefinition();
999 if (!Record)
1000 return;
1001
Fangrui Song050229d2018-11-24 00:14:31 +00001002 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001003 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001004 R.CursorKind = getCursorKindForDecl(R.Declaration);
1005 Results.push_back(R);
1006 }
1007}
1008
Sam McCall63c59722018-01-22 20:44:47 +00001009static bool isConstructor(const Decl *ND) {
1010 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
1011 ND = Tmpl->getTemplatedDecl();
1012 return isa<CXXConstructorDecl>(ND);
1013}
1014
Douglas Gregor7c208612010-01-14 00:20:49 +00001015void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
1016 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001017
Douglas Gregor7c208612010-01-14 00:20:49 +00001018 if (R.Kind != Result::RK_Declaration) {
1019 // For non-declaration results, just add the result.
1020 Results.push_back(R);
1021 return;
1022 }
1023
1024 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001025 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
1026 CodeCompletionResult Result(Using->getTargetDecl(),
1027 getBasePriority(Using->getTargetDecl()),
1028 R.Qualifier);
1029 Result.ShadowDecl = Using;
1030 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +00001031 return;
1032 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001033
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001034 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +00001035 unsigned IDNS = CanonDecl->getIdentifierNamespace();
1036
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001037 bool AsNestedNameSpecifier = false;
1038 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +00001039 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001040
Douglas Gregor0212fd72010-09-21 16:06:22 +00001041 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001042 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001043 return;
1044
Douglas Gregor3545ff42009-09-21 16:56:56 +00001045 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001046 ShadowMapEntry::iterator I, IEnd;
1047 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
1048 if (NamePos != SMap.end()) {
1049 I = NamePos->second.begin();
1050 IEnd = NamePos->second.end();
1051 }
1052
1053 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001054 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001055 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001056 if (ND->getCanonicalDecl() == CanonDecl) {
1057 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001058 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001059
Douglas Gregor3545ff42009-09-21 16:56:56 +00001060 // We're done.
1061 return;
1062 }
1063 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001064
Douglas Gregor3545ff42009-09-21 16:56:56 +00001065 // This is a new declaration in this scope. However, check whether this
1066 // declaration name is hidden by a similarly-named declaration in an outer
1067 // scope.
1068 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
1069 --SMEnd;
1070 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001071 ShadowMapEntry::iterator I, IEnd;
1072 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
1073 if (NamePos != SM->end()) {
1074 I = NamePos->second.begin();
1075 IEnd = NamePos->second.end();
1076 }
1077 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001078 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +00001079 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +00001080 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
1081 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001082 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001083
Douglas Gregor3545ff42009-09-21 16:56:56 +00001084 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +00001085 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
1086 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001087 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001088 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001089
Douglas Gregor3545ff42009-09-21 16:56:56 +00001090 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +00001091 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001092 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001093
Douglas Gregor3545ff42009-09-21 16:56:56 +00001094 break;
1095 }
1096 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001097
Douglas Gregor3545ff42009-09-21 16:56:56 +00001098 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001099 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001100 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00001101
Douglas Gregore412a5a2009-09-23 22:26:46 +00001102 // If the filter is for nested-name-specifiers, then this result starts a
1103 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001104 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +00001105 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001106 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001107 } else
Fangrui Song050229d2018-11-24 00:14:31 +00001108 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001109
Douglas Gregor5bf52692009-09-22 23:15:58 +00001110 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +00001111 if (R.QualifierIsInformative && !R.Qualifier &&
1112 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001113 const DeclContext *Ctx = R.Declaration->getDeclContext();
1114 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001115 R.Qualifier =
1116 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001117 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001118 R.Qualifier = NestedNameSpecifier::Create(
1119 SemaRef.Context, nullptr, false,
1120 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +00001121 else
1122 R.QualifierIsInformative = false;
1123 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001124
Douglas Gregor3545ff42009-09-21 16:56:56 +00001125 // Insert this result into the set of results and into the current shadow
1126 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001127 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001128 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001129
Douglas Gregor0212fd72010-09-21 16:06:22 +00001130 if (!AsNestedNameSpecifier)
1131 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001132}
1133
Eric Liu4a7cd632018-10-24 12:57:27 +00001134static void setInBaseClass(ResultBuilder::Result &R) {
1135 R.Priority += CCD_InBaseClass;
1136 R.InBaseClass = true;
1137}
1138
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001139void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +00001140 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001141 if (R.Kind != Result::RK_Declaration) {
1142 // For non-declaration results, just add the result.
1143 Results.push_back(R);
1144 return;
1145 }
1146
Douglas Gregorc580c522010-01-14 01:09:38 +00001147 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +00001148 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001149 CodeCompletionResult Result(Using->getTargetDecl(),
1150 getBasePriority(Using->getTargetDecl()),
1151 R.Qualifier);
1152 Result.ShadowDecl = Using;
1153 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +00001154 return;
1155 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001156
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001157 bool AsNestedNameSpecifier = false;
1158 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +00001159 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001160
Douglas Gregor0212fd72010-09-21 16:06:22 +00001161 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001162 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001163 return;
1164
Douglas Gregorc580c522010-01-14 01:09:38 +00001165 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1166 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001167
Douglas Gregorc580c522010-01-14 01:09:38 +00001168 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001169 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001170 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001171
Douglas Gregorc580c522010-01-14 01:09:38 +00001172 // If the filter is for nested-name-specifiers, then this result starts a
1173 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001174 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001175 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001176 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001177 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1178 InBaseClass &&
1179 isa<CXXRecordDecl>(
1180 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001181 R.QualifierIsInformative = true;
1182
Douglas Gregorc580c522010-01-14 01:09:38 +00001183 // If this result is supposed to have an informative qualifier, add one.
1184 if (R.QualifierIsInformative && !R.Qualifier &&
1185 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001186 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001187 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1188 R.Qualifier =
1189 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1190 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1191 R.Qualifier = NestedNameSpecifier::Create(
1192 SemaRef.Context, nullptr, false,
1193 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001194 else
1195 R.QualifierIsInformative = false;
1196 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001197
Douglas Gregora2db7932010-05-26 22:00:08 +00001198 // Adjust the priority if this result comes from a base class.
1199 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001200 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001201
Douglas Gregor50832e02010-09-20 22:39:41 +00001202 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001203
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001204 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001205 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001206 if (Method->isInstance()) {
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00001207 Qualifiers MethodQuals = Method->getMethodQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001208 if (ObjectTypeQualifiers == MethodQuals)
1209 R.Priority += CCD_ObjectQualifierMatch;
1210 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001211 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001212 // qualifiers.
1213 return;
1214 }
1215 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001216
Douglas Gregorc580c522010-01-14 01:09:38 +00001217 // Insert this result into the set of results.
1218 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001219
Douglas Gregor0212fd72010-09-21 16:06:22 +00001220 if (!AsNestedNameSpecifier)
1221 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001222}
1223
Douglas Gregor78a21012010-01-14 16:01:26 +00001224void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001225 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001226 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001227 Results.push_back(R);
1228}
1229
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001230/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001231void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001232
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001233/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001234void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001235 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00001236 EEnd = ShadowMaps.back().end();
1237 E != EEnd; ++E)
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001238 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001239
Douglas Gregor3545ff42009-09-21 16:56:56 +00001240 ShadowMaps.pop_back();
1241}
1242
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001243/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001244/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001245bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001246 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001247
Richard Smith541b38b2013-09-20 01:15:31 +00001248 // If name lookup finds a local extern declaration, then we are in a
1249 // context where it behaves like an ordinary name.
1250 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001251 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001252 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001253 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001254 if (isa<ObjCIvarDecl>(ND))
1255 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001256 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001257
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001258 return ND->getIdentifierNamespace() & IDNS;
1259}
1260
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001261/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001262/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001263bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001264 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001265 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001266 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001267 // Objective-C interfaces names are not filtered by this method because they
1268 // can be used in a class property expression. We can still filter out
1269 // @class declarations though.
1270 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1271 if (!ID->getDefinition())
1272 return false;
1273 }
1274
Richard Smith541b38b2013-09-20 01:15:31 +00001275 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001276 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001277 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001278 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001279 if (isa<ObjCIvarDecl>(ND))
1280 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001281 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001282
Douglas Gregor70febae2010-05-28 00:49:12 +00001283 return ND->getIdentifierNamespace() & IDNS;
1284}
1285
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001286bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001287 if (!IsOrdinaryNonTypeName(ND))
1288 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001289
Fangrui Song050229d2018-11-24 00:14:31 +00001290 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001291 if (VD->getType()->isIntegralOrEnumerationType())
1292 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001293
Douglas Gregor85b50632010-07-28 21:50:18 +00001294 return false;
1295}
1296
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001297/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001298/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001299bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001300 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001301
Richard Smith541b38b2013-09-20 01:15:31 +00001302 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001303 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001304 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001305
Fangrui Song050229d2018-11-24 00:14:31 +00001306 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1307 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001308}
1309
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001310/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001311/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001312bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001313 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001314 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001315 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001316
Douglas Gregor3545ff42009-09-21 16:56:56 +00001317 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1318}
1319
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001320/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001321bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001322 return isa<EnumDecl>(ND);
1323}
1324
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001325/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001326bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001327 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001328 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001329 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001330
1331 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001332 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1333 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1334 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001335
Douglas Gregor3545ff42009-09-21 16:56:56 +00001336 return false;
1337}
1338
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001339/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001340bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001341 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001342 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001343 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001344
Fangrui Song050229d2018-11-24 00:14:31 +00001345 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001346 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001347
Douglas Gregor3545ff42009-09-21 16:56:56 +00001348 return false;
1349}
1350
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001351/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001352bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001353 return isa<NamespaceDecl>(ND);
1354}
1355
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001356/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001357/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001358bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001359 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001360}
1361
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001362/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001363bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001364 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001365 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001366}
1367
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001368/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001369/// "." or "->". Only value declarations, nested name specifiers, and
1370/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001371bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001372 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001373 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001374 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001375}
1376
Douglas Gregora817a192010-05-27 23:06:34 +00001377static bool isObjCReceiverType(ASTContext &C, QualType T) {
1378 T = C.getCanonicalType(T);
1379 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001380 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001381 case Type::ObjCInterface:
1382 case Type::ObjCObjectPointer:
1383 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001384
Douglas Gregora817a192010-05-27 23:06:34 +00001385 case Type::Builtin:
1386 switch (cast<BuiltinType>(T)->getKind()) {
1387 case BuiltinType::ObjCId:
1388 case BuiltinType::ObjCClass:
1389 case BuiltinType::ObjCSel:
1390 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001391
Douglas Gregora817a192010-05-27 23:06:34 +00001392 default:
1393 break;
1394 }
1395 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001396
Douglas Gregora817a192010-05-27 23:06:34 +00001397 default:
1398 break;
1399 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001400
David Blaikiebbafb8a2012-03-11 07:00:24 +00001401 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001402 return false;
1403
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001404 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001405 // particular class type has any conversions to Objective-C types. For now,
1406 // just accept all class types.
1407 return T->isDependentType() || T->isRecordType();
1408}
1409
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001410bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001411 QualType T = getDeclUsageType(SemaRef.Context, ND);
1412 if (T.isNull())
1413 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001414
Douglas Gregora817a192010-05-27 23:06:34 +00001415 T = SemaRef.Context.getBaseElementType(T);
1416 return isObjCReceiverType(SemaRef.Context, T);
1417}
1418
Fangrui Song050229d2018-11-24 00:14:31 +00001419bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1420 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001421 if (IsObjCMessageReceiver(ND))
1422 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001423
Fangrui Song050229d2018-11-24 00:14:31 +00001424 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001425 if (!Var)
1426 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001427
Douglas Gregord8c61782012-02-15 15:34:24 +00001428 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1429}
1430
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001431bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001432 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1433 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001434 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001435
Douglas Gregor68762e72010-08-23 21:17:50 +00001436 QualType T = getDeclUsageType(SemaRef.Context, ND);
1437 if (T.isNull())
1438 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001439
Douglas Gregor68762e72010-08-23 21:17:50 +00001440 T = SemaRef.Context.getBaseElementType(T);
1441 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001442 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001443 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001444}
Douglas Gregora817a192010-05-27 23:06:34 +00001445
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001446bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001447 return false;
1448}
1449
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001450/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001451/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001452bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001453 return isa<ObjCIvarDecl>(ND);
1454}
1455
Douglas Gregorc580c522010-01-14 01:09:38 +00001456namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001457
Fangrui Song050229d2018-11-24 00:14:31 +00001458/// Visible declaration consumer that adds a code-completion result
1459/// for each visible declaration.
1460class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1461 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001462 DeclContext *InitialLookupCtx;
1463 // NamingClass and BaseType are used for access-checking. See
1464 // Sema::IsSimplyAccessible for details.
1465 CXXRecordDecl *NamingClass;
1466 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001467 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001468
Fangrui Song050229d2018-11-24 00:14:31 +00001469public:
1470 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001471 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1472 QualType BaseType = QualType(),
1473 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1474 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1475 FixIts(std::move(FixIts)) {
1476 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1477 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1478 if (BaseType.isNull()) {
1479 auto ThisType = Results.getSema().getCurrentThisType();
1480 if (!ThisType.isNull()) {
1481 assert(ThisType->isPointerType());
1482 BaseType = ThisType->getPointeeType();
1483 if (!NamingClass)
1484 NamingClass = BaseType->getAsCXXRecordDecl();
1485 }
1486 }
1487 this->BaseType = BaseType;
1488 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001489
Fangrui Song050229d2018-11-24 00:14:31 +00001490 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1491 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001492 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001493 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001494 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001495 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001496
Fangrui Song050229d2018-11-24 00:14:31 +00001497 void EnteredContext(DeclContext *Ctx) override {
1498 Results.addVisitedContext(Ctx);
1499 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001500
1501private:
1502 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1503 // Naming class to use for access check. In most cases it was provided
1504 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1505 // for unqualified lookup we fallback to the \p Ctx in which we found the
1506 // member.
1507 auto *NamingClass = this->NamingClass;
1508 QualType BaseType = this->BaseType;
1509 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1510 if (!NamingClass)
1511 NamingClass = Cls;
1512 // When we emulate implicit 'this->' in an unqualified lookup, we might
1513 // end up with an invalid naming class. In that case, we avoid emulating
1514 // 'this->' qualifier to satisfy preconditions of the access checking.
1515 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1516 !NamingClass->isDerivedFrom(Cls)) {
1517 NamingClass = Cls;
1518 BaseType = QualType();
1519 }
1520 } else {
1521 // The decl was found outside the C++ class, so only ObjC access checks
1522 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1523 // out.
1524 NamingClass = nullptr;
1525 BaseType = QualType();
1526 }
1527 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1528 }
Fangrui Song050229d2018-11-24 00:14:31 +00001529};
1530} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001531
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001532/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001533static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001534 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001535 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001536 Results.AddResult(Result("short", CCP_Type));
1537 Results.AddResult(Result("long", CCP_Type));
1538 Results.AddResult(Result("signed", CCP_Type));
1539 Results.AddResult(Result("unsigned", CCP_Type));
1540 Results.AddResult(Result("void", CCP_Type));
1541 Results.AddResult(Result("char", CCP_Type));
1542 Results.AddResult(Result("int", CCP_Type));
1543 Results.AddResult(Result("float", CCP_Type));
1544 Results.AddResult(Result("double", CCP_Type));
1545 Results.AddResult(Result("enum", CCP_Type));
1546 Results.AddResult(Result("struct", CCP_Type));
1547 Results.AddResult(Result("union", CCP_Type));
1548 Results.AddResult(Result("const", CCP_Type));
1549 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001550
Douglas Gregor3545ff42009-09-21 16:56:56 +00001551 if (LangOpts.C99) {
1552 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001553 Results.AddResult(Result("_Complex", CCP_Type));
1554 Results.AddResult(Result("_Imaginary", CCP_Type));
1555 Results.AddResult(Result("_Bool", CCP_Type));
1556 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001557 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001558
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001559 CodeCompletionBuilder Builder(Results.getAllocator(),
1560 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001561 if (LangOpts.CPlusPlus) {
1562 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001563 Results.AddResult(
1564 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001565 Results.AddResult(Result("class", CCP_Type));
1566 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001567
Douglas Gregorf4c33342010-05-28 00:22:41 +00001568 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001569 Builder.AddTypedTextChunk("typename");
1570 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1571 Builder.AddPlaceholderChunk("qualifier");
1572 Builder.AddTextChunk("::");
1573 Builder.AddPlaceholderChunk("name");
1574 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001575
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001576 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001577 Results.AddResult(Result("auto", CCP_Type));
1578 Results.AddResult(Result("char16_t", CCP_Type));
1579 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001580
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001581 Builder.AddTypedTextChunk("decltype");
1582 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1583 Builder.AddPlaceholderChunk("expression");
1584 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1585 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001586 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001587 } else
1588 Results.AddResult(Result("__auto_type", CCP_Type));
1589
Richard Smith7b301e22018-05-24 21:51:52 +00001590 // GNU keywords
1591 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001592 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001593 // Results.AddResult(Result("_Decimal32"));
1594 // Results.AddResult(Result("_Decimal64"));
1595 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001596
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001597 Builder.AddTypedTextChunk("typeof");
1598 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1599 Builder.AddPlaceholderChunk("expression");
1600 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001601
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001602 Builder.AddTypedTextChunk("typeof");
1603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1604 Builder.AddPlaceholderChunk("type");
1605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1606 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001607 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001608
1609 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001610 Results.AddResult(Result("_Nonnull", CCP_Type));
1611 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1612 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001613}
1614
John McCallfaf5fb42010-08-26 23:41:50 +00001615static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001616 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001617 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001618 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001619 // Note: we don't suggest either "auto" or "register", because both
1620 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1621 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001622 Results.AddResult(Result("extern"));
1623 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001624
1625 if (LangOpts.CPlusPlus11) {
1626 CodeCompletionAllocator &Allocator = Results.getAllocator();
1627 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1628
1629 // alignas
1630 Builder.AddTypedTextChunk("alignas");
1631 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1632 Builder.AddPlaceholderChunk("expression");
1633 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1634 Results.AddResult(Result(Builder.TakeString()));
1635
1636 Results.AddResult(Result("constexpr"));
1637 Results.AddResult(Result("thread_local"));
1638 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001639}
1640
John McCallfaf5fb42010-08-26 23:41:50 +00001641static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001642 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001643 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001644 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001645 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001646 case Sema::PCC_Class:
1647 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001648 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001649 Results.AddResult(Result("explicit"));
1650 Results.AddResult(Result("friend"));
1651 Results.AddResult(Result("mutable"));
1652 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001653 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001654 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001655
John McCallfaf5fb42010-08-26 23:41:50 +00001656 case Sema::PCC_ObjCInterface:
1657 case Sema::PCC_ObjCImplementation:
1658 case Sema::PCC_Namespace:
1659 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001660 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001661 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001662 break;
1663
John McCallfaf5fb42010-08-26 23:41:50 +00001664 case Sema::PCC_ObjCInstanceVariableList:
1665 case Sema::PCC_Expression:
1666 case Sema::PCC_Statement:
1667 case Sema::PCC_ForInit:
1668 case Sema::PCC_Condition:
1669 case Sema::PCC_RecoveryInFunction:
1670 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001671 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001672 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001673 break;
1674 }
1675}
1676
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001677static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1678static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1679static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001680 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001681static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001682 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001683static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001684 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001685static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001686
Douglas Gregorf4c33342010-05-28 00:22:41 +00001687static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001688 CodeCompletionBuilder Builder(Results.getAllocator(),
1689 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001690 Builder.AddTypedTextChunk("typedef");
1691 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1692 Builder.AddPlaceholderChunk("type");
1693 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1694 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001695 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001696}
1697
John McCallfaf5fb42010-08-26 23:41:50 +00001698static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001699 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001700 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001701 case Sema::PCC_Namespace:
1702 case Sema::PCC_Class:
1703 case Sema::PCC_ObjCInstanceVariableList:
1704 case Sema::PCC_Template:
1705 case Sema::PCC_MemberTemplate:
1706 case Sema::PCC_Statement:
1707 case Sema::PCC_RecoveryInFunction:
1708 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001709 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001710 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001711 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001712
John McCallfaf5fb42010-08-26 23:41:50 +00001713 case Sema::PCC_Expression:
1714 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001715 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001716
Douglas Gregor5e35d592010-09-14 23:59:36 +00001717 case Sema::PCC_ObjCInterface:
1718 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001719 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001720
John McCallfaf5fb42010-08-26 23:41:50 +00001721 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001722 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001723 }
David Blaikie8a40f702012-01-17 06:56:22 +00001724
1725 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001726}
1727
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001728static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1729 const Preprocessor &PP) {
1730 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001731 Policy.AnonymousTagLocations = false;
1732 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001733 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001734 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001735 return Policy;
1736}
1737
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001738/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001739static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1740 return getCompletionPrintingPolicy(S.Context, S.PP);
1741}
1742
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001743/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001744/// that has the appropriate lifetime for code completion.
1745///
1746/// This routine provides a fast path where we provide constant strings for
1747/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001748static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001749 const PrintingPolicy &Policy,
1750 CodeCompletionAllocator &Allocator) {
1751 if (!T.getLocalQualifiers()) {
1752 // Built-in type names are constant strings.
1753 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001754 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001755
Douglas Gregore5c79d52011-10-18 21:20:17 +00001756 // Anonymous tag types are constant strings.
1757 if (const TagType *TagT = dyn_cast<TagType>(T))
1758 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001759 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001760 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001761 case TTK_Struct:
1762 return "struct <anonymous>";
1763 case TTK_Interface:
1764 return "__interface <anonymous>";
1765 case TTK_Class:
1766 return "class <anonymous>";
1767 case TTK_Union:
1768 return "union <anonymous>";
1769 case TTK_Enum:
1770 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001771 }
1772 }
1773 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001774
Douglas Gregore5c79d52011-10-18 21:20:17 +00001775 // Slow path: format the type as a string.
1776 std::string Result;
1777 T.getAsStringInternal(Result, Policy);
1778 return Allocator.CopyString(Result);
1779}
1780
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001781/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001782static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1783 QualType ThisTy = S.getCurrentThisType();
1784 if (ThisTy.isNull())
1785 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001786
Douglas Gregord8c61782012-02-15 15:34:24 +00001787 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001788 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001789 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001790 Builder.AddResultTypeChunk(
1791 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001792 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001793 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001794}
1795
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001796static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1797 ResultBuilder &Results,
1798 const LangOptions &LangOpts) {
1799 if (!LangOpts.CPlusPlus11)
1800 return;
1801
1802 Builder.AddTypedTextChunk("static_assert");
1803 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1804 Builder.AddPlaceholderChunk("expression");
1805 Builder.AddChunk(CodeCompletionString::CK_Comma);
1806 Builder.AddPlaceholderChunk("message");
1807 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1808 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1809}
1810
Fangrui Song050229d2018-11-24 00:14:31 +00001811static void printOverrideString(llvm::raw_ostream &OS,
1812 CodeCompletionString *CCS) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001813 for (const auto &C : *CCS) {
1814 if (C.Kind == CodeCompletionString::CK_Optional)
1815 printOverrideString(OS, C.Optional);
1816 else
1817 OS << C.Text;
1818 // Add a space after return type.
1819 if (C.Kind == CodeCompletionString::CK_ResultType)
1820 OS << ' ';
1821 }
1822}
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001823
1824static void AddOverrideResults(ResultBuilder &Results,
1825 const CodeCompletionContext &CCContext,
1826 CodeCompletionBuilder &Builder) {
1827 Sema &S = Results.getSema();
1828 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1829 // If not inside a class/struct/union return empty.
1830 if (!CR)
1831 return;
1832 // First store overrides within current class.
1833 // These are stored by name to make querying fast in the later step.
1834 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1835 for (auto *Method : CR->methods()) {
1836 if (!Method->isVirtual() || !Method->getIdentifier())
1837 continue;
1838 Overrides[Method->getName()].push_back(Method);
1839 }
1840
1841 for (const auto &Base : CR->bases()) {
1842 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1843 if (!BR)
1844 continue;
1845 for (auto *Method : BR->methods()) {
1846 if (!Method->isVirtual() || !Method->getIdentifier())
1847 continue;
1848 const auto it = Overrides.find(Method->getName());
1849 bool IsOverriden = false;
1850 if (it != Overrides.end()) {
1851 for (auto *MD : it->second) {
1852 // If the method in current body is not an overload of this virtual
1853 // function, then it overrides this one.
1854 if (!S.IsOverload(MD, Method, false)) {
1855 IsOverriden = true;
1856 break;
1857 }
1858 }
1859 }
1860 if (!IsOverriden) {
1861 // Generates a new CodeCompletionResult by taking this function and
1862 // converting it into an override declaration with only one chunk in the
1863 // final CodeCompletionString as a TypedTextChunk.
1864 std::string OverrideSignature;
1865 llvm::raw_string_ostream OS(OverrideSignature);
1866 CodeCompletionResult CCR(Method, 0);
1867 PrintingPolicy Policy =
1868 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1869 auto *CCS = CCR.createCodeCompletionStringForOverride(
1870 S.getPreprocessor(), S.getASTContext(), Builder,
1871 /*IncludeBriefComments=*/false, CCContext, Policy);
1872 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1873 }
1874 }
1875 }
1876}
1877
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001878/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001879static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1880 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001881 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001882 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001883
John McCall276321a2010-08-25 06:19:51 +00001884 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001885 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001886 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001887 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001888 if (Results.includeCodePatterns()) {
1889 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001890 Builder.AddTypedTextChunk("namespace");
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddPlaceholderChunk("identifier");
1893 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1894 Builder.AddPlaceholderChunk("declarations");
1895 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1896 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1897 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001898 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001899
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001900 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001901 Builder.AddTypedTextChunk("namespace");
1902 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1903 Builder.AddPlaceholderChunk("name");
1904 Builder.AddChunk(CodeCompletionString::CK_Equal);
1905 Builder.AddPlaceholderChunk("namespace");
1906 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001907
1908 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001909 Builder.AddTypedTextChunk("using");
1910 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1911 Builder.AddTextChunk("namespace");
1912 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1913 Builder.AddPlaceholderChunk("identifier");
1914 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001915
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001916 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001917 Builder.AddTypedTextChunk("asm");
1918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1919 Builder.AddPlaceholderChunk("string-literal");
1920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1921 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001922
Douglas Gregorf4c33342010-05-28 00:22:41 +00001923 if (Results.includeCodePatterns()) {
1924 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001925 Builder.AddTypedTextChunk("template");
1926 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1927 Builder.AddPlaceholderChunk("declaration");
1928 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001929 } else {
1930 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001931 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001932 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001933
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001934 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001935 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001936
Douglas Gregorf4c33342010-05-28 00:22:41 +00001937 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001938 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001939
John McCallfaf5fb42010-08-26 23:41:50 +00001940 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001941 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001942 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001943 Builder.AddTypedTextChunk("using");
1944 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1945 Builder.AddPlaceholderChunk("qualifier");
1946 Builder.AddTextChunk("::");
1947 Builder.AddPlaceholderChunk("name");
1948 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001949
Douglas Gregorf4c33342010-05-28 00:22:41 +00001950 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001951 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001952 Builder.AddTypedTextChunk("using");
1953 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1954 Builder.AddTextChunk("typename");
1955 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1956 Builder.AddPlaceholderChunk("qualifier");
1957 Builder.AddTextChunk("::");
1958 Builder.AddPlaceholderChunk("name");
1959 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001960 }
1961
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001962 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1963
John McCallfaf5fb42010-08-26 23:41:50 +00001964 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001965 AddTypedefResult(Results);
1966
Erik Verbruggen6524c052017-10-24 13:46:58 +00001967 bool IsNotInheritanceScope =
1968 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001969 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001970 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001971 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001972 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001973 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001974
1975 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001976 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001977 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001978 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001980
1981 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001982 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001983 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001984 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001985 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001986
1987 // FIXME: This adds override results only if we are at the first word of
1988 // the declaration/definition. Also call this from other sides to have
1989 // more use-cases.
1990 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
1991 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001992 }
1993 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001994 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001995
John McCallfaf5fb42010-08-26 23:41:50 +00001996 case Sema::PCC_Template:
1997 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001998 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001999 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002000 Builder.AddTypedTextChunk("template");
2001 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2002 Builder.AddPlaceholderChunk("parameters");
2003 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2004 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002005 } else {
2006 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002007 }
2008
David Blaikiebbafb8a2012-03-11 07:00:24 +00002009 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2010 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002011 break;
2012
John McCallfaf5fb42010-08-26 23:41:50 +00002013 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002014 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2015 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2016 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002017 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002018
John McCallfaf5fb42010-08-26 23:41:50 +00002019 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002020 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2021 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2022 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002023 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002024
John McCallfaf5fb42010-08-26 23:41:50 +00002025 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002026 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002027 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002028
John McCallfaf5fb42010-08-26 23:41:50 +00002029 case Sema::PCC_RecoveryInFunction:
2030 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002031 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002032
David Blaikiebbafb8a2012-03-11 07:00:24 +00002033 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2034 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002035 Builder.AddTypedTextChunk("try");
2036 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2037 Builder.AddPlaceholderChunk("statements");
2038 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2039 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2040 Builder.AddTextChunk("catch");
2041 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2042 Builder.AddPlaceholderChunk("declaration");
2043 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2044 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2045 Builder.AddPlaceholderChunk("statements");
2046 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2047 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2048 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002049 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002050 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002051 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002052
Douglas Gregorf64acca2010-05-25 21:41:55 +00002053 if (Results.includeCodePatterns()) {
2054 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002055 Builder.AddTypedTextChunk("if");
2056 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002057 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002058 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002059 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002060 Builder.AddPlaceholderChunk("expression");
2061 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2062 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2063 Builder.AddPlaceholderChunk("statements");
2064 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2065 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2066 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002067
Douglas Gregorf64acca2010-05-25 21:41:55 +00002068 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002069 Builder.AddTypedTextChunk("switch");
2070 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002071 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002072 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002073 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002074 Builder.AddPlaceholderChunk("expression");
2075 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2076 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2077 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2078 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2079 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002080 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002081
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002082 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002083 if (SemaRef.getCurFunction() &&
2084 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002085 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002086 Builder.AddTypedTextChunk("case");
2087 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2088 Builder.AddPlaceholderChunk("expression");
2089 Builder.AddChunk(CodeCompletionString::CK_Colon);
2090 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002091
2092 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002093 Builder.AddTypedTextChunk("default");
2094 Builder.AddChunk(CodeCompletionString::CK_Colon);
2095 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002096 }
2097
Douglas Gregorf64acca2010-05-25 21:41:55 +00002098 if (Results.includeCodePatterns()) {
2099 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002100 Builder.AddTypedTextChunk("while");
2101 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002102 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002103 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002104 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002105 Builder.AddPlaceholderChunk("expression");
2106 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2107 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2108 Builder.AddPlaceholderChunk("statements");
2109 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2110 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2111 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002112
2113 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002114 Builder.AddTypedTextChunk("do");
2115 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2116 Builder.AddPlaceholderChunk("statements");
2117 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2118 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2119 Builder.AddTextChunk("while");
2120 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2121 Builder.AddPlaceholderChunk("expression");
2122 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2123 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002124
Douglas Gregorf64acca2010-05-25 21:41:55 +00002125 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002126 Builder.AddTypedTextChunk("for");
2127 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002128 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002129 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002130 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002131 Builder.AddPlaceholderChunk("init-expression");
2132 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2133 Builder.AddPlaceholderChunk("condition");
2134 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2135 Builder.AddPlaceholderChunk("inc-expression");
2136 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2137 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2138 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2139 Builder.AddPlaceholderChunk("statements");
2140 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2141 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2142 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002143 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002144
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002145 if (S->getContinueParent()) {
2146 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002147 Builder.AddTypedTextChunk("continue");
2148 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002149 }
2150
2151 if (S->getBreakParent()) {
2152 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002153 Builder.AddTypedTextChunk("break");
2154 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002155 }
2156
2157 // "return expression ;" or "return ;", depending on whether we
2158 // know the function is void or not.
2159 bool isVoid = false;
Fangrui Song050229d2018-11-24 00:14:31 +00002160 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00002161 isVoid = Function->getReturnType()->isVoidType();
Fangrui Song050229d2018-11-24 00:14:31 +00002162 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00002163 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002164 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002165 !SemaRef.getCurBlock()->ReturnType.isNull())
2166 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002167 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00002168 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002169 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2170 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00002171 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002172 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002173
Douglas Gregorf4c33342010-05-28 00:22:41 +00002174 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002175 Builder.AddTypedTextChunk("goto");
2176 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2177 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002178 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002179
Douglas Gregorf4c33342010-05-28 00:22:41 +00002180 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002181 Builder.AddTypedTextChunk("using");
2182 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2183 Builder.AddTextChunk("namespace");
2184 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2185 Builder.AddPlaceholderChunk("identifier");
2186 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002187
2188 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002189 }
Fangrui Song050229d2018-11-24 00:14:31 +00002190 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002191
2192 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002193 case Sema::PCC_ForInit:
2194 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002195 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002196 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002197 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002198
Douglas Gregor5e35d592010-09-14 23:59:36 +00002199 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002200 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002201 CCC == Sema::PCC_ParenthesizedExpression) {
2202 // (__bridge <type>)<expression>
2203 Builder.AddTypedTextChunk("__bridge");
2204 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2205 Builder.AddPlaceholderChunk("type");
2206 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2207 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002208 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002209
2210 // (__bridge_transfer <Objective-C type>)<expression>
2211 Builder.AddTypedTextChunk("__bridge_transfer");
2212 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2213 Builder.AddPlaceholderChunk("Objective-C type");
2214 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2215 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002216 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002217
2218 // (__bridge_retained <CF type>)<expression>
2219 Builder.AddTypedTextChunk("__bridge_retained");
2220 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2221 Builder.AddPlaceholderChunk("CF type");
2222 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2223 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002224 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002225 }
2226 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002227 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002228
John McCallfaf5fb42010-08-26 23:41:50 +00002229 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002230 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002231 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002232 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002233
Douglas Gregore5c79d52011-10-18 21:20:17 +00002234 // true
2235 Builder.AddResultTypeChunk("bool");
2236 Builder.AddTypedTextChunk("true");
2237 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002238
Douglas Gregore5c79d52011-10-18 21:20:17 +00002239 // false
2240 Builder.AddResultTypeChunk("bool");
2241 Builder.AddTypedTextChunk("false");
2242 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002243
David Blaikiebbafb8a2012-03-11 07:00:24 +00002244 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002245 // dynamic_cast < type-id > ( expression )
2246 Builder.AddTypedTextChunk("dynamic_cast");
2247 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2248 Builder.AddPlaceholderChunk("type");
2249 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2250 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2251 Builder.AddPlaceholderChunk("expression");
2252 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002253 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002254 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002255
Douglas Gregorf4c33342010-05-28 00:22:41 +00002256 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002257 Builder.AddTypedTextChunk("static_cast");
2258 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2259 Builder.AddPlaceholderChunk("type");
2260 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2261 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2262 Builder.AddPlaceholderChunk("expression");
2263 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002264 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002265
Douglas Gregorf4c33342010-05-28 00:22:41 +00002266 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002267 Builder.AddTypedTextChunk("reinterpret_cast");
2268 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2269 Builder.AddPlaceholderChunk("type");
2270 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2271 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2272 Builder.AddPlaceholderChunk("expression");
2273 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002274 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002275
Douglas Gregorf4c33342010-05-28 00:22:41 +00002276 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002277 Builder.AddTypedTextChunk("const_cast");
2278 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2279 Builder.AddPlaceholderChunk("type");
2280 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2281 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2282 Builder.AddPlaceholderChunk("expression");
2283 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002284 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002285
David Blaikiebbafb8a2012-03-11 07:00:24 +00002286 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002287 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002288 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002289 Builder.AddTypedTextChunk("typeid");
2290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2291 Builder.AddPlaceholderChunk("expression-or-type");
2292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002293 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002294 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002295
Douglas Gregorf4c33342010-05-28 00:22:41 +00002296 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002297 Builder.AddTypedTextChunk("new");
2298 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2299 Builder.AddPlaceholderChunk("type");
2300 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2301 Builder.AddPlaceholderChunk("expressions");
2302 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002303 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002304
Douglas Gregorf4c33342010-05-28 00:22:41 +00002305 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002306 Builder.AddTypedTextChunk("new");
2307 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2308 Builder.AddPlaceholderChunk("type");
2309 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2310 Builder.AddPlaceholderChunk("size");
2311 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2312 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2313 Builder.AddPlaceholderChunk("expressions");
2314 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002315 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002316
Douglas Gregorf4c33342010-05-28 00:22:41 +00002317 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002318 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002319 Builder.AddTypedTextChunk("delete");
2320 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2321 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002322 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002323
Douglas Gregorf4c33342010-05-28 00:22:41 +00002324 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002325 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002326 Builder.AddTypedTextChunk("delete");
2327 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2328 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2329 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2330 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2331 Builder.AddPlaceholderChunk("expression");
2332 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002333
David Blaikiebbafb8a2012-03-11 07:00:24 +00002334 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002335 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002336 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002337 Builder.AddTypedTextChunk("throw");
2338 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2339 Builder.AddPlaceholderChunk("expression");
2340 Results.AddResult(Result(Builder.TakeString()));
2341 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002342
Douglas Gregora2db7932010-05-26 22:00:08 +00002343 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002344
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002345 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002346 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002347 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002348 Builder.AddTypedTextChunk("nullptr");
2349 Results.AddResult(Result(Builder.TakeString()));
2350
2351 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002352 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002353 Builder.AddTypedTextChunk("alignof");
2354 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2355 Builder.AddPlaceholderChunk("type");
2356 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2357 Results.AddResult(Result(Builder.TakeString()));
2358
2359 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002360 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002361 Builder.AddTypedTextChunk("noexcept");
2362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2363 Builder.AddPlaceholderChunk("expression");
2364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2365 Results.AddResult(Result(Builder.TakeString()));
2366
2367 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002368 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002369 Builder.AddTypedTextChunk("sizeof...");
2370 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2371 Builder.AddPlaceholderChunk("parameter-pack");
2372 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2373 Results.AddResult(Result(Builder.TakeString()));
2374 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002375 }
2376
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002377 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002378 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002379 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2380 // The interface can be NULL.
2381 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002382 if (ID->getSuperClass()) {
2383 std::string SuperType;
2384 SuperType = ID->getSuperClass()->getNameAsString();
2385 if (Method->isInstanceMethod())
2386 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002387
Douglas Gregore5c79d52011-10-18 21:20:17 +00002388 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2389 Builder.AddTypedTextChunk("super");
2390 Results.AddResult(Result(Builder.TakeString()));
2391 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002392 }
2393
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002394 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002395 }
2396
Jordan Rose58d54722012-06-30 21:33:57 +00002397 if (SemaRef.getLangOpts().C11) {
2398 // _Alignof
2399 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002400 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002401 Builder.AddTypedTextChunk("alignof");
2402 else
2403 Builder.AddTypedTextChunk("_Alignof");
2404 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2405 Builder.AddPlaceholderChunk("type");
2406 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2407 Results.AddResult(Result(Builder.TakeString()));
2408 }
2409
Douglas Gregorf4c33342010-05-28 00:22:41 +00002410 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002411 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002412 Builder.AddTypedTextChunk("sizeof");
2413 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2414 Builder.AddPlaceholderChunk("expression-or-type");
2415 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2416 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002417 break;
2418 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002419
John McCallfaf5fb42010-08-26 23:41:50 +00002420 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002421 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002422 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002423 }
2424
David Blaikiebbafb8a2012-03-11 07:00:24 +00002425 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2426 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002427
David Blaikiebbafb8a2012-03-11 07:00:24 +00002428 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002429 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002430}
2431
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002432/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002433/// type chunk.
2434static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002435 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002436 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002437 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002438 if (!ND)
2439 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002440
2441 // Skip constructors and conversion functions, which have their return types
2442 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002443 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002444 return;
2445
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002446 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002447 QualType T;
2448 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002449 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002450 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002451 if (!BaseType.isNull())
2452 T = Method->getSendResultType(BaseType);
2453 else
2454 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002455 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002456 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002457 T = clang::TypeName::getFullyQualifiedType(T, Context);
2458 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002459 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002460 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002461 if (!BaseType.isNull())
2462 T = Ivar->getUsageType(BaseType);
2463 else
2464 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002465 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002466 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002467 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002468 if (!BaseType.isNull())
2469 T = Property->getUsageType(BaseType);
2470 else
2471 T = Property->getType();
2472 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002473
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002474 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2475 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002476
Fangrui Song050229d2018-11-24 00:14:31 +00002477 Result.AddResultTypeChunk(
2478 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002479}
2480
Richard Smith20e883e2015-04-29 23:20:19 +00002481static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002482 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002483 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002484 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2485 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002486 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002487 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002488 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002489 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002490 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002491 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002492 }
2493}
2494
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002495static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002496 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002497 std::string Result;
2498 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002499 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002500 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002501 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002502 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002503 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002504 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002505 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002506 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002507 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002508 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002509 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002510 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2511 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2512 switch (*nullability) {
2513 case NullabilityKind::NonNull:
2514 Result += "nonnull ";
2515 break;
2516
2517 case NullabilityKind::Nullable:
2518 Result += "nullable ";
2519 break;
2520
2521 case NullabilityKind::Unspecified:
2522 Result += "null_unspecified ";
2523 break;
2524 }
2525 }
2526 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002527 return Result;
2528}
2529
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002530/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002531/// block placeholder.
2532///
2533/// This function ignores things like typedefs and qualifiers in order to
2534/// present the most relevant and accurate block placeholders in code completion
2535/// results.
2536static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2537 FunctionTypeLoc &Block,
2538 FunctionProtoTypeLoc &BlockProto,
2539 bool SuppressBlock = false) {
2540 if (!TSInfo)
2541 return;
2542 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2543 while (true) {
2544 // Look through typedefs.
2545 if (!SuppressBlock) {
2546 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2547 if (TypeSourceInfo *InnerTSInfo =
2548 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2549 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2550 continue;
2551 }
2552 }
2553
2554 // Look through qualified types
2555 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2556 TL = QualifiedTL.getUnqualifiedLoc();
2557 continue;
2558 }
2559
2560 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2561 TL = AttrTL.getModifiedLoc();
2562 continue;
2563 }
2564 }
2565
2566 // Try to get the function prototype behind the block pointer type,
2567 // then we're done.
2568 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2569 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2570 Block = TL.getAs<FunctionTypeLoc>();
2571 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2572 }
2573 break;
2574 }
2575}
2576
Alex Lorenz920ae142016-10-18 10:38:58 +00002577static std::string
2578formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2579 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002580 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002581 bool SuppressBlock = false,
2582 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2583
Fangrui Song050229d2018-11-24 00:14:31 +00002584static std::string
2585FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2586 bool SuppressName = false, bool SuppressBlock = false,
2587 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002588 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2589 if (Param->getType()->isDependentType() ||
2590 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002591 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002592 // containing that parameter's type.
2593 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002594
Douglas Gregor981a0c42010-08-29 19:47:46 +00002595 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002596 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002597
Douglas Gregor86b42682015-06-19 18:27:52 +00002598 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002599 if (ObjCSubsts)
2600 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2601 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002602 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002603 Result =
2604 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002605 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002606 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002607 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002608 } else {
2609 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002610 }
2611 return Result;
2612 }
Alex Lorenza1951202016-10-18 10:35:27 +00002613
Douglas Gregore90dd002010-08-24 16:15:59 +00002614 // The argument for a block pointer parameter is a block literal with
2615 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002616 FunctionTypeLoc Block;
2617 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002618 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2619 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002620 // Try to retrieve the block type information from the property if this is a
2621 // parameter in a setter.
2622 if (!Block && ObjCMethodParam &&
2623 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2624 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2625 ->findPropertyDecl(/*CheckOverrides=*/false))
2626 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2627 SuppressBlock);
2628 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002629
2630 if (!Block) {
2631 // We were unable to find a FunctionProtoTypeLoc with parameter names
2632 // for the block; just use the parameter type as a placeholder.
2633 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002634 if (!ObjCMethodParam && Param->getIdentifier())
2635 Result = Param->getIdentifier()->getName();
2636
Douglas Gregor86b42682015-06-19 18:27:52 +00002637 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002638
Douglas Gregore90dd002010-08-24 16:15:59 +00002639 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002640 Result = Type.getAsString(Policy);
2641 std::string Quals =
2642 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2643 if (!Quals.empty())
2644 Result = "(" + Quals + " " + Result + ")";
2645 if (Result.back() != ')')
2646 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002647 if (Param->getIdentifier())
2648 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002649 } else {
2650 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002651 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002652
Douglas Gregore90dd002010-08-24 16:15:59 +00002653 return Result;
2654 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002655
Douglas Gregore90dd002010-08-24 16:15:59 +00002656 // We have the function prototype behind the block pointer type, as it was
2657 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002658 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2659 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002660 ObjCSubsts);
2661}
2662
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002663/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002664/// declaration.
2665///
2666/// \param BlockDecl A declaration with an Objective-C block type.
2667///
2668/// \param Block The most relevant type location for that block type.
2669///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002670/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002671/// declaration is included in the resulting string.
2672static std::string
2673formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2674 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002675 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002676 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002677 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002678 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002679 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002680 ResultType =
2681 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2682 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002683 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002684 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002685
2686 // Format the parameter list.
2687 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002688 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002689 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002690 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002691 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002692 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002693 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002694 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002695 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002696 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002697 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002698 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002699 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002700 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002701
David Blaikie6adc78e2013-02-18 22:06:02 +00002702 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002703 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002704 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002705 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002706 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002707
Douglas Gregord793e7c2011-10-18 04:23:19 +00002708 if (SuppressBlock) {
2709 // Format as a parameter.
2710 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002711 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002712 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002713 Result += ")";
2714 Result += Params;
2715 } else {
2716 // Format as a block literal argument.
2717 Result = '^' + Result;
2718 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002719
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002720 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002721 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002722 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002723
Douglas Gregore90dd002010-08-24 16:15:59 +00002724 return Result;
2725}
2726
Erik Verbruggen11338c52017-07-19 10:45:40 +00002727static std::string GetDefaultValueString(const ParmVarDecl *Param,
2728 const SourceManager &SM,
2729 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002730 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002731 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2732 bool Invalid = CharSrcRange.isInvalid();
2733 if (Invalid)
2734 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002735 StringRef srcText =
2736 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002737 if (Invalid)
2738 return "";
2739
2740 if (srcText.empty() || srcText == "=") {
2741 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002742 // This happens if the code is incorrect (for example class is forward
2743 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002744 return "";
2745 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002746 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002747 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2748 // this value always has (or always does not have) '=' in front of it
2749 if (DefValue.at(0) != '=') {
2750 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002751 // Lexer returns built-in types values without '=' and user-defined types
2752 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002753 return " = " + DefValue;
2754 }
2755 return " " + DefValue;
2756}
2757
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002758/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002759static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002760 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002761 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002762 CodeCompletionBuilder &Result,
2763 unsigned Start = 0,
2764 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002765 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002766
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002767 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002768 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002769
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002770 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002771 // When we see an optional default argument, put that argument and
2772 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002773 CodeCompletionBuilder Opt(Result.getAllocator(),
2774 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002775 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002776 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002777 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002778 Result.AddOptionalChunk(Opt.TakeString());
2779 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002780 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002781
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002782 if (FirstParameter)
2783 FirstParameter = false;
2784 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002785 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002786
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002787 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002788
Douglas Gregor3545ff42009-09-21 16:56:56 +00002789 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002790 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002791 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002792 PlaceholderStr +=
2793 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002794
Douglas Gregor400f5972010-08-31 05:13:43 +00002795 if (Function->isVariadic() && P == N - 1)
2796 PlaceholderStr += ", ...";
2797
Douglas Gregor3545ff42009-09-21 16:56:56 +00002798 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002799 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002800 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002801 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002802
Fangrui Song050229d2018-11-24 00:14:31 +00002803 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002804 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002805 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002806 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002807
Richard Smith20e883e2015-04-29 23:20:19 +00002808 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002809 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002810}
2811
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002812/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002813static void AddTemplateParameterChunks(
2814 ASTContext &Context, const PrintingPolicy &Policy,
2815 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2816 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002817 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002818
2819 // Prefer to take the template parameter names from the first declaration of
2820 // the template.
2821 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2822
Douglas Gregor3545ff42009-09-21 16:56:56 +00002823 TemplateParameterList *Params = Template->getTemplateParameters();
2824 TemplateParameterList::iterator PEnd = Params->end();
2825 if (MaxParameters)
2826 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002827 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2828 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002829 bool HasDefaultArg = false;
2830 std::string PlaceholderStr;
2831 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2832 if (TTP->wasDeclaredWithTypename())
2833 PlaceholderStr = "typename";
2834 else
2835 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002836
Douglas Gregor3545ff42009-09-21 16:56:56 +00002837 if (TTP->getIdentifier()) {
2838 PlaceholderStr += ' ';
2839 PlaceholderStr += TTP->getIdentifier()->getName();
2840 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002841
Douglas Gregor3545ff42009-09-21 16:56:56 +00002842 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002843 } else if (NonTypeTemplateParmDecl *NTTP =
2844 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002845 if (NTTP->getIdentifier())
2846 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002847 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002848 HasDefaultArg = NTTP->hasDefaultArgument();
2849 } else {
2850 assert(isa<TemplateTemplateParmDecl>(*P));
2851 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002852
Douglas Gregor3545ff42009-09-21 16:56:56 +00002853 // Since putting the template argument list into the placeholder would
2854 // be very, very long, we just use an abbreviation.
2855 PlaceholderStr = "template<...> class";
2856 if (TTP->getIdentifier()) {
2857 PlaceholderStr += ' ';
2858 PlaceholderStr += TTP->getIdentifier()->getName();
2859 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002860
Douglas Gregor3545ff42009-09-21 16:56:56 +00002861 HasDefaultArg = TTP->hasDefaultArgument();
2862 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002863
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002864 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002865 // When we see an optional default argument, put that argument and
2866 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002867 CodeCompletionBuilder Opt(Result.getAllocator(),
2868 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002869 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002870 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002871 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002872 P - Params->begin(), true);
2873 Result.AddOptionalChunk(Opt.TakeString());
2874 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002875 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002876
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002877 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002878
Douglas Gregor3545ff42009-09-21 16:56:56 +00002879 if (FirstParameter)
2880 FirstParameter = false;
2881 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002882 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002883
Douglas Gregor3545ff42009-09-21 16:56:56 +00002884 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002885 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002886 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002887 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002888}
2889
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002890/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002891/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002892static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2893 NestedNameSpecifier *Qualifier,
2894 bool QualifierIsInformative,
2895 ASTContext &Context,
2896 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002897 if (!Qualifier)
2898 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002899
Douglas Gregorf2510672009-09-21 19:57:38 +00002900 std::string PrintedNNS;
2901 {
2902 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002903 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002904 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002905 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002906 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002907 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002908 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002909}
2910
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002911static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002912AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002913 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002914 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002915 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00002916 return;
2917
Douglas Gregor304f9b02011-02-01 21:15:40 +00002918 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002919
Douglas Gregor304f9b02011-02-01 21:15:40 +00002920 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002921 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002922 Result.AddInformativeChunk(" const");
2923 return;
2924 }
2925
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002926 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002927 Result.AddInformativeChunk(" volatile");
2928 return;
2929 }
2930
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002931 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002932 Result.AddInformativeChunk(" restrict");
2933 return;
2934 }
2935
2936 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002937 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002938 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002939 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002940 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002941 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002942 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002943 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002944 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002945}
2946
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002947/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002948static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002949 const NamedDecl *ND,
2950 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002951 DeclarationName Name = ND->getDeclName();
2952 if (!Name)
2953 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002954
Douglas Gregor0212fd72010-09-21 16:06:22 +00002955 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002956 case DeclarationName::CXXOperatorName: {
2957 const char *OperatorName = nullptr;
2958 switch (Name.getCXXOverloadedOperator()) {
2959 case OO_None:
2960 case OO_Conditional:
2961 case NUM_OVERLOADED_OPERATORS:
2962 OperatorName = "operator";
2963 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002964
Fangrui Song050229d2018-11-24 00:14:31 +00002965#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
2966 case OO_##Name: \
2967 OperatorName = "operator" Spelling; \
2968 break;
2969#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00002970#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002971
Fangrui Song050229d2018-11-24 00:14:31 +00002972 case OO_New:
2973 OperatorName = "operator new";
2974 break;
2975 case OO_Delete:
2976 OperatorName = "operator delete";
2977 break;
2978 case OO_Array_New:
2979 OperatorName = "operator new[]";
2980 break;
2981 case OO_Array_Delete:
2982 OperatorName = "operator delete[]";
2983 break;
2984 case OO_Call:
2985 OperatorName = "operator()";
2986 break;
2987 case OO_Subscript:
2988 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002989 break;
2990 }
Fangrui Song050229d2018-11-24 00:14:31 +00002991 Result.AddTypedTextChunk(OperatorName);
2992 break;
2993 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002994
Douglas Gregor0212fd72010-09-21 16:06:22 +00002995 case DeclarationName::Identifier:
2996 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002997 case DeclarationName::CXXDestructorName:
2998 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002999 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003000 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003001 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003002
Richard Smith35845152017-02-07 01:37:30 +00003003 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003004 case DeclarationName::CXXUsingDirective:
3005 case DeclarationName::ObjCZeroArgSelector:
3006 case DeclarationName::ObjCOneArgSelector:
3007 case DeclarationName::ObjCMultiArgSelector:
3008 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003009
Douglas Gregor0212fd72010-09-21 16:06:22 +00003010 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003011 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003012 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003013 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003014 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003015 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003016 Record = InjectedTy->getDecl();
3017 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003018 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003019 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003020 break;
3021 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003022
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003023 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003024 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003025 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003026 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003027 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003028 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003029 }
3030 break;
3031 }
3032 }
3033}
3034
Fangrui Song050229d2018-11-24 00:14:31 +00003035CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3036 Sema &S, const CodeCompletionContext &CCContext,
3037 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3038 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003039 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3040 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003041}
3042
Eric Liu00f43c92018-07-06 09:43:57 +00003043CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3044 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3045 CodeCompletionTUInfo &CCTUInfo) {
3046 assert(Kind == RK_Macro);
3047 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3048 const MacroInfo *MI = PP.getMacroInfo(Macro);
3049 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3050
3051 if (!MI || !MI->isFunctionLike())
3052 return Result.TakeString();
3053
3054 // Format a function-like macro with placeholders for the arguments.
3055 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3056 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3057
3058 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3059 if (MI->isC99Varargs()) {
3060 --AEnd;
3061
3062 if (A == AEnd) {
3063 Result.AddPlaceholderChunk("...");
3064 }
3065 }
3066
3067 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3068 if (A != MI->param_begin())
3069 Result.AddChunk(CodeCompletionString::CK_Comma);
3070
3071 if (MI->isVariadic() && (A + 1) == AEnd) {
3072 SmallString<32> Arg = (*A)->getName();
3073 if (MI->isC99Varargs())
3074 Arg += ", ...";
3075 else
3076 Arg += "...";
3077 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3078 break;
3079 }
3080
3081 // Non-variadic macros are simple.
3082 Result.AddPlaceholderChunk(
3083 Result.getAllocator().CopyString((*A)->getName()));
3084 }
3085 Result.AddChunk(CodeCompletionString::CK_RightParen);
3086 return Result.TakeString();
3087}
3088
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003089/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003090/// result.
3091///
3092/// \returns Either a new, heap-allocated code completion string describing
3093/// how to use this result, or NULL to indicate that the string or name of the
3094/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003095CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3096 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3097 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3098 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003099 if (Kind == RK_Macro)
3100 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3101
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003102 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003103
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003104 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003105 if (Kind == RK_Pattern) {
3106 Pattern->Priority = Priority;
3107 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003108
Douglas Gregor78254c82012-03-27 23:34:16 +00003109 if (Declaration) {
3110 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003111 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003112 if (const RawComment *RC =
3113 getPatternCompletionComment(Ctx, Declaration)) {
3114 Result.addBriefComment(RC->getBriefText(Ctx));
3115 Pattern->BriefComment = Result.getBriefComment();
3116 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003117 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003118
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003119 return Pattern;
3120 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003121
Douglas Gregorf09935f2009-12-01 05:55:20 +00003122 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003123 Result.AddTypedTextChunk(Keyword);
3124 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003125 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003126 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003127 return createCodeCompletionStringForDecl(
3128 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003129}
3130
3131CodeCompletionString *
3132CodeCompletionResult::createCodeCompletionStringForOverride(
3133 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3134 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3135 PrintingPolicy &Policy) {
3136 std::string OverrideSignature;
3137 llvm::raw_string_ostream OS(OverrideSignature);
3138 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3139 /*IncludeBriefComments=*/false,
3140 CCContext, Policy);
3141 printOverrideString(OS, CCS);
3142 OS << " override";
3143 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
3144 return Result.TakeString();
3145}
3146
3147CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3148 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3149 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3150 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003151 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003152 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003153
3154 if (IncludeBriefComments) {
3155 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003156 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003157 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003158 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003159 }
3160
Douglas Gregor9eb77012009-11-07 00:00:49 +00003161 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003162 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003163 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003164 Result.AddTextChunk("::");
3165 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003166 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003167
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003168 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3169 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003170
Douglas Gregorc3425b12015-07-07 06:20:19 +00003171 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003172
Fangrui Song050229d2018-11-24 00:14:31 +00003173 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003174 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003175 Ctx, Policy);
3176 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003177 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003178 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003179 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003180 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003181 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003182 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003183
Fangrui Song050229d2018-11-24 00:14:31 +00003184 if (const FunctionTemplateDecl *FunTmpl =
3185 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003186 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003187 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003188 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003189 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003190
Douglas Gregor3545ff42009-09-21 16:56:56 +00003191 // Figure out which template parameters are deduced (or have default
3192 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003193 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003194 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003195 unsigned LastDeducibleArgument;
3196 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3197 --LastDeducibleArgument) {
3198 if (!Deduced[LastDeducibleArgument - 1]) {
3199 // C++0x: Figure out if the template argument has a default. If so,
3200 // the user doesn't need to type this argument.
3201 // FIXME: We need to abstract template parameters better!
3202 bool HasDefaultArg = false;
3203 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003204 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003205 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3206 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003207 else if (NonTypeTemplateParmDecl *NTTP =
3208 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003209 HasDefaultArg = NTTP->hasDefaultArgument();
3210 else {
3211 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003212 HasDefaultArg =
3213 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003214 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003215
Douglas Gregor3545ff42009-09-21 16:56:56 +00003216 if (!HasDefaultArg)
3217 break;
3218 }
3219 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003220
Douglas Gregor3545ff42009-09-21 16:56:56 +00003221 if (LastDeducibleArgument) {
3222 // Some of the function template arguments cannot be deduced from a
3223 // function call, so we introduce an explicit template argument list
3224 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003225 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003226 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003227 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003228 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003229 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003230
Douglas Gregor3545ff42009-09-21 16:56:56 +00003231 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003232 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003233 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003234 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003235 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003236 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003237 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003238
Fangrui Song050229d2018-11-24 00:14:31 +00003239 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003240 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003241 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003242 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003243 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003244 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003245 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003246 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003247 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003248 }
Fangrui Song050229d2018-11-24 00:14:31 +00003249 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003250 Selector Sel = Method->getSelector();
3251 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003252 Result.AddTypedTextChunk(
3253 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003254 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003255 }
3256
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003257 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003258 SelName += ':';
3259 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003260 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003261 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003262 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003263
Douglas Gregor1b605f72009-11-19 01:08:35 +00003264 // If there is only one parameter, and we're past it, add an empty
3265 // typed-text chunk since there is nothing to type.
3266 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003267 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003268 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003269 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003270 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003271 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003272 P != PEnd; (void)++P, ++Idx) {
3273 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003274 std::string Keyword;
3275 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003276 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003277 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003278 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003279 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003280 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003281 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003282 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003283 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003284 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003285
Douglas Gregor1b605f72009-11-19 01:08:35 +00003286 // If we're before the starting parameter, skip the placeholder.
3287 if (Idx < StartParameter)
3288 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003289
3290 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003291 QualType ParamType = (*P)->getType();
3292 Optional<ArrayRef<QualType>> ObjCSubsts;
3293 if (!CCContext.getBaseType().isNull())
3294 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3295
3296 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3297 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003298 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003299 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003300 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003301 ParamType = ParamType.substObjCTypeArgs(
3302 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003303 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003304 ParamType);
3305 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003306 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003307 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003308 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003309 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003310
Douglas Gregor400f5972010-08-31 05:13:43 +00003311 if (Method->isVariadic() && (P + 1) == PEnd)
3312 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003313
Douglas Gregor95887f92010-07-08 23:20:03 +00003314 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003315 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003316 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003317 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003318 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003319 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003320 }
3321
Douglas Gregor04c5f972009-12-23 00:21:46 +00003322 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003323 if (Method->param_size() == 0) {
3324 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003325 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003326 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003327 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003328 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003329 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003330 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003331
Richard Smith20e883e2015-04-29 23:20:19 +00003332 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003333 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003334
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003335 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003336 }
3337
Douglas Gregorf09935f2009-12-01 05:55:20 +00003338 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003339 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003340 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003341
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003342 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003343 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003344 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003345}
3346
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003347const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3348 const NamedDecl *ND) {
3349 if (!ND)
3350 return nullptr;
3351 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3352 return RC;
3353
3354 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003355 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003356 if (!M)
3357 return nullptr;
3358 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3359 if (!PDecl)
3360 return nullptr;
3361
3362 return Ctx.getRawCommentForAnyRedecl(PDecl);
3363}
3364
3365const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3366 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003367 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003368 if (!M || !M->isPropertyAccessor())
3369 return nullptr;
3370
3371 // Provide code completion comment for self.GetterName where
3372 // GetterName is the getter method for a property with name
3373 // different from the property name (declared via a property
3374 // getter attribute.
3375 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3376 if (!PDecl)
3377 return nullptr;
3378 if (PDecl->getGetterName() == M->getSelector() &&
3379 PDecl->getIdentifier() != M->getIdentifier()) {
3380 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3381 return RC;
3382 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3383 return RC;
3384 }
3385 return nullptr;
3386}
3387
3388const RawComment *clang::getParameterComment(
3389 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003390 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003391 auto FDecl = Result.getFunction();
3392 if (!FDecl)
3393 return nullptr;
3394 if (ArgIndex < FDecl->getNumParams())
3395 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3396 return nullptr;
3397}
3398
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003399/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003400/// string.
3401static void AddOverloadParameterChunks(ASTContext &Context,
3402 const PrintingPolicy &Policy,
3403 const FunctionDecl *Function,
3404 const FunctionProtoType *Prototype,
3405 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003406 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003407 bool InOptional = false) {
3408 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003409 unsigned NumParams =
3410 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003411
3412 for (unsigned P = Start; P != NumParams; ++P) {
3413 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3414 // When we see an optional default argument, put that argument and
3415 // the remaining default arguments into a new, optional string.
3416 CodeCompletionBuilder Opt(Result.getAllocator(),
3417 Result.getCodeCompletionTUInfo());
3418 if (!FirstParameter)
3419 Opt.AddChunk(CodeCompletionString::CK_Comma);
3420 // Optional sections are nested.
3421 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3422 CurrentArg, P, /*InOptional=*/true);
3423 Result.AddOptionalChunk(Opt.TakeString());
3424 return;
3425 }
3426
3427 if (FirstParameter)
3428 FirstParameter = false;
3429 else
3430 Result.AddChunk(CodeCompletionString::CK_Comma);
3431
3432 InOptional = false;
3433
3434 // Format the placeholder string.
3435 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003436 if (Function) {
3437 const ParmVarDecl *Param = Function->getParamDecl(P);
3438 Placeholder = FormatFunctionParameter(Policy, Param);
3439 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003440 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3441 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003442 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003443 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003444 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003445
3446 if (P == CurrentArg)
3447 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003448 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003449 else
3450 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3451 }
3452
3453 if (Prototype && Prototype->isVariadic()) {
3454 CodeCompletionBuilder Opt(Result.getAllocator(),
3455 Result.getCodeCompletionTUInfo());
3456 if (!FirstParameter)
3457 Opt.AddChunk(CodeCompletionString::CK_Comma);
3458
3459 if (CurrentArg < NumParams)
3460 Opt.AddPlaceholderChunk("...");
3461 else
3462 Opt.AddCurrentParameterChunk("...");
3463
3464 Result.AddOptionalChunk(Opt.TakeString());
3465 }
3466}
3467
Douglas Gregorf0f51982009-09-23 00:34:09 +00003468CodeCompletionString *
3469CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003470 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3471 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003472 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003473
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003474 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003475 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3476 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003477 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003478 const FunctionProtoType *Proto =
3479 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003480 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003481 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003482 // highlighted ellipsis.
3483 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003484 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003485 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003486 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3487 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3488 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003489 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003490 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003491
3492 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003493 if (IncludeBriefComments) {
3494 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003495 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003496 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003497 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003498 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003499 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003500 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003501 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003502 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003503 }
Alp Toker314cc812014-01-25 16:55:45 +00003504
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003505 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003506 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3507 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003508 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003509
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003510 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003511}
3512
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003513unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003514 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003515 bool PreferredTypeIsPointer) {
3516 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003517
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003518 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003519 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003520 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003521 Priority = CCP_Constant;
3522 if (PreferredTypeIsPointer)
3523 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003524 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003525 // Treat "YES", "NO", "true", and "false" as constants.
3526 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3527 MacroName.equals("true") || MacroName.equals("false"))
3528 Priority = CCP_Constant;
3529 // Treat "bool" as a type.
3530 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003531 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003532
Douglas Gregor6e240332010-08-16 16:18:59 +00003533 return Priority;
3534}
3535
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003536CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003537 if (!D)
3538 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003539
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003540 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003541 case Decl::Enum:
3542 return CXCursor_EnumDecl;
3543 case Decl::EnumConstant:
3544 return CXCursor_EnumConstantDecl;
3545 case Decl::Field:
3546 return CXCursor_FieldDecl;
3547 case Decl::Function:
3548 return CXCursor_FunctionDecl;
3549 case Decl::ObjCCategory:
3550 return CXCursor_ObjCCategoryDecl;
3551 case Decl::ObjCCategoryImpl:
3552 return CXCursor_ObjCCategoryImplDecl;
3553 case Decl::ObjCImplementation:
3554 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003555
Fangrui Song050229d2018-11-24 00:14:31 +00003556 case Decl::ObjCInterface:
3557 return CXCursor_ObjCInterfaceDecl;
3558 case Decl::ObjCIvar:
3559 return CXCursor_ObjCIvarDecl;
3560 case Decl::ObjCMethod:
3561 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3562 ? CXCursor_ObjCInstanceMethodDecl
3563 : CXCursor_ObjCClassMethodDecl;
3564 case Decl::CXXMethod:
3565 return CXCursor_CXXMethod;
3566 case Decl::CXXConstructor:
3567 return CXCursor_Constructor;
3568 case Decl::CXXDestructor:
3569 return CXCursor_Destructor;
3570 case Decl::CXXConversion:
3571 return CXCursor_ConversionFunction;
3572 case Decl::ObjCProperty:
3573 return CXCursor_ObjCPropertyDecl;
3574 case Decl::ObjCProtocol:
3575 return CXCursor_ObjCProtocolDecl;
3576 case Decl::ParmVar:
3577 return CXCursor_ParmDecl;
3578 case Decl::Typedef:
3579 return CXCursor_TypedefDecl;
3580 case Decl::TypeAlias:
3581 return CXCursor_TypeAliasDecl;
3582 case Decl::TypeAliasTemplate:
3583 return CXCursor_TypeAliasTemplateDecl;
3584 case Decl::Var:
3585 return CXCursor_VarDecl;
3586 case Decl::Namespace:
3587 return CXCursor_Namespace;
3588 case Decl::NamespaceAlias:
3589 return CXCursor_NamespaceAlias;
3590 case Decl::TemplateTypeParm:
3591 return CXCursor_TemplateTypeParameter;
3592 case Decl::NonTypeTemplateParm:
3593 return CXCursor_NonTypeTemplateParameter;
3594 case Decl::TemplateTemplateParm:
3595 return CXCursor_TemplateTemplateParameter;
3596 case Decl::FunctionTemplate:
3597 return CXCursor_FunctionTemplate;
3598 case Decl::ClassTemplate:
3599 return CXCursor_ClassTemplate;
3600 case Decl::AccessSpec:
3601 return CXCursor_CXXAccessSpecifier;
3602 case Decl::ClassTemplatePartialSpecialization:
3603 return CXCursor_ClassTemplatePartialSpecialization;
3604 case Decl::UsingDirective:
3605 return CXCursor_UsingDirective;
3606 case Decl::StaticAssert:
3607 return CXCursor_StaticAssert;
3608 case Decl::Friend:
3609 return CXCursor_FriendDecl;
3610 case Decl::TranslationUnit:
3611 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003612
Fangrui Song050229d2018-11-24 00:14:31 +00003613 case Decl::Using:
3614 case Decl::UnresolvedUsingValue:
3615 case Decl::UnresolvedUsingTypename:
3616 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003617
Fangrui Song050229d2018-11-24 00:14:31 +00003618 case Decl::ObjCPropertyImpl:
3619 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3620 case ObjCPropertyImplDecl::Dynamic:
3621 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003622
Fangrui Song050229d2018-11-24 00:14:31 +00003623 case ObjCPropertyImplDecl::Synthesize:
3624 return CXCursor_ObjCSynthesizeDecl;
3625 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003626 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003627
3628 case Decl::Import:
3629 return CXCursor_ModuleImportDecl;
3630
3631 case Decl::ObjCTypeParam:
3632 return CXCursor_TemplateTypeParameter;
3633
3634 default:
3635 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3636 switch (TD->getTagKind()) {
3637 case TTK_Interface: // fall through
3638 case TTK_Struct:
3639 return CXCursor_StructDecl;
3640 case TTK_Class:
3641 return CXCursor_ClassDecl;
3642 case TTK_Union:
3643 return CXCursor_UnionDecl;
3644 case TTK_Enum:
3645 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003646 }
Fangrui Song050229d2018-11-24 00:14:31 +00003647 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003648 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003649
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003650 return CXCursor_UnexposedDecl;
3651}
3652
Douglas Gregor55b037b2010-07-08 20:55:51 +00003653static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003654 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003655 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003656 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003657
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003658 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003659
Eric Liu88de9f62018-09-19 09:34:55 +00003660 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3661 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003662 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003663 auto MD = PP.getMacroDefinition(M->first);
3664 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003665 MacroInfo *MI = MD.getMacroInfo();
3666 if (MI && MI->isUsedForHeaderGuard())
3667 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003668
Eric Liud485df12018-09-05 14:59:17 +00003669 Results.AddResult(
3670 Result(M->first, MI,
3671 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3672 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003673 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003674 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003675
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003676 Results.ExitScope();
3677}
3678
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003679static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003680 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003681 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003682
Douglas Gregorce0e8562010-08-23 21:54:33 +00003683 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003684
Douglas Gregorce0e8562010-08-23 21:54:33 +00003685 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3686 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003687 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003688 Results.AddResult(Result("__func__", CCP_Constant));
3689 Results.ExitScope();
3690}
3691
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003692static void HandleCodeCompleteResults(Sema *S,
3693 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003694 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003695 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003696 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003697 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003698 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003699}
3700
Ilya Biryukov41109672018-12-13 15:36:32 +00003701static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003702mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003703 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003704 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003705 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003706
John McCallfaf5fb42010-08-26 23:41:50 +00003707 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003708 return CodeCompletionContext::CCC_ClassStructUnion;
3709
John McCallfaf5fb42010-08-26 23:41:50 +00003710 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003711 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003712
John McCallfaf5fb42010-08-26 23:41:50 +00003713 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003714 return CodeCompletionContext::CCC_ObjCImplementation;
3715
John McCallfaf5fb42010-08-26 23:41:50 +00003716 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003717 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003718
John McCallfaf5fb42010-08-26 23:41:50 +00003719 case Sema::PCC_Template:
3720 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003721 if (S.CurContext->isFileContext())
3722 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003723 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003724 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003725 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003726
John McCallfaf5fb42010-08-26 23:41:50 +00003727 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003728 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003729
John McCallfaf5fb42010-08-26 23:41:50 +00003730 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003731 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003732 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003733 return CodeCompletionContext::CCC_ParenthesizedExpression;
3734 else
3735 return CodeCompletionContext::CCC_Expression;
3736
3737 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003738 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003739 case Sema::PCC_Condition:
3740 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3741 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003742
John McCallfaf5fb42010-08-26 23:41:50 +00003743 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003744 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003745
John McCallfaf5fb42010-08-26 23:41:50 +00003746 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003747 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003748
3749 case Sema::PCC_ParenthesizedExpression:
3750 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003751
Douglas Gregor80039242011-02-15 20:33:25 +00003752 case Sema::PCC_LocalDeclarationSpecifiers:
3753 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003754 }
David Blaikie8a40f702012-01-17 06:56:22 +00003755
3756 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003757}
3758
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003759/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003760/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003761/// overridden function as well as adding new functionality.
3762///
3763/// \param S The semantic analysis object for which we are generating results.
3764///
3765/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003766/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003767static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3768 ResultBuilder &Results) {
3769 // Look through blocks.
3770 DeclContext *CurContext = S.CurContext;
3771 while (isa<BlockDecl>(CurContext))
3772 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003773
Douglas Gregorac322ec2010-08-27 21:18:54 +00003774 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3775 if (!Method || !Method->isVirtual())
3776 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003777
3778 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003779 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003780 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003781 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003782 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003783
Douglas Gregor75acd922011-09-27 23:30:47 +00003784 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003785 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003786 CodeCompletionBuilder Builder(Results.getAllocator(),
3787 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003788 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3789 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003790
Douglas Gregorac322ec2010-08-27 21:18:54 +00003791 // If we need a nested-name-specifier, add one now.
3792 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003793 NestedNameSpecifier *NNS = getRequiredQualification(
3794 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003795 if (NNS) {
3796 std::string Str;
3797 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003798 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003799 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003800 }
3801 } else if (!InContext->Equals(Overridden->getDeclContext()))
3802 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003803
Fangrui Song050229d2018-11-24 00:14:31 +00003804 Builder.AddTypedTextChunk(
3805 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003806 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003807 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003808 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003809 if (FirstParam)
3810 FirstParam = false;
3811 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003812 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003813
Aaron Ballman43b68be2014-03-07 17:50:17 +00003814 Builder.AddPlaceholderChunk(
3815 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003816 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003817 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003818 Results.AddResult(CodeCompletionResult(
3819 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3820 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003821 Results.Ignore(Overridden);
3822 }
3823}
3824
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003825void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003826 ModuleIdPath Path) {
3827 typedef CodeCompletionResult Result;
3828 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003829 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003830 CodeCompletionContext::CCC_Other);
3831 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003832
Douglas Gregor07f43572012-01-29 18:15:03 +00003833 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003834 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003835 typedef CodeCompletionResult Result;
3836 if (Path.empty()) {
3837 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003838 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003839 PP.getHeaderSearchInfo().collectAllModules(Modules);
3840 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3841 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003842 Builder.getAllocator().CopyString(Modules[I]->Name));
3843 Results.AddResult(Result(
3844 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3845 Modules[I]->isAvailable() ? CXAvailability_Available
3846 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003847 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003848 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003849 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003850 Module *Mod =
3851 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3852 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003853 // Enumerate submodules.
3854 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003855 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003856 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003857 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003858
Douglas Gregor07f43572012-01-29 18:15:03 +00003859 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003860 Builder.getAllocator().CopyString((*Sub)->Name));
3861 Results.AddResult(Result(
3862 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3863 (*Sub)->isAvailable() ? CXAvailability_Available
3864 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003865 }
3866 }
3867 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003868 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003869 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003870 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003871}
3872
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003873void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003874 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003875 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003876 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003877 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003878 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003879
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003880 // Determine how to filter results, e.g., so that the names of
3881 // values (functions, enumerators, function templates, etc.) are
3882 // only allowed where we can have an expression.
3883 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003884 case PCC_Namespace:
3885 case PCC_Class:
3886 case PCC_ObjCInterface:
3887 case PCC_ObjCImplementation:
3888 case PCC_ObjCInstanceVariableList:
3889 case PCC_Template:
3890 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003891 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003892 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003893 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3894 break;
3895
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003896 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003897 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003898 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003899 case PCC_ForInit:
3900 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003901 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003902 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3903 else
3904 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003905
David Blaikiebbafb8a2012-03-11 07:00:24 +00003906 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003907 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003908 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003909
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003910 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003911 // Unfiltered
3912 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003913 }
3914
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003915 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003916 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00003917 auto ThisType = getCurrentThisType();
3918 if (!ThisType.isNull())
3919 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003920
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003921 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003922 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003923 CodeCompleter->includeGlobals(),
3924 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003925
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003926 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003927 Results.ExitScope();
3928
Douglas Gregorce0e8562010-08-23 21:54:33 +00003929 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003930 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003931 case PCC_Expression:
3932 case PCC_Statement:
3933 case PCC_RecoveryInFunction:
3934 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003935 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003936 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003937
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003938 case PCC_Namespace:
3939 case PCC_Class:
3940 case PCC_ObjCInterface:
3941 case PCC_ObjCImplementation:
3942 case PCC_ObjCInstanceVariableList:
3943 case PCC_Template:
3944 case PCC_MemberTemplate:
3945 case PCC_ForInit:
3946 case PCC_Condition:
3947 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003948 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003949 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003950 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003951
Douglas Gregor9eb77012009-11-07 00:00:49 +00003952 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003953 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003954
Douglas Gregor50832e02010-09-20 22:39:41 +00003955 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003956 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003957}
3958
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003959static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003960 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003961 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00003962 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003963 ResultBuilder &Results);
3964
3965void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3966 bool AllowNonIdentifiers,
3967 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003968 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00003969 ResultBuilder Results(
3970 *this, CodeCompleter->getAllocator(),
3971 CodeCompleter->getCodeCompletionTUInfo(),
3972 AllowNestedNameSpecifiers
3973 // FIXME: Try to separate codepath leading here to deduce whether we
3974 // need an existing symbol or a new one.
3975 ? CodeCompletionContext::CCC_SymbolOrNewName
3976 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003977 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003978
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003979 // Type qualifiers can come after names.
3980 Results.AddResult(Result("const"));
3981 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003982 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003983 Results.AddResult(Result("restrict"));
3984
David Blaikiebbafb8a2012-03-11 07:00:24 +00003985 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003986 if (getLangOpts().CPlusPlus11 &&
3987 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3988 DS.getTypeSpecType() == DeclSpec::TST_struct))
3989 Results.AddResult("final");
3990
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003991 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003992 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003993 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003994
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003995 // Add nested-name-specifiers.
3996 if (AllowNestedNameSpecifiers) {
3997 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003998 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003999 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4000 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004001 CodeCompleter->includeGlobals(),
4002 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004003 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004004 }
4005 }
4006 Results.ExitScope();
4007
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004008 // If we're in a context where we might have an expression (rather than a
4009 // declaration), and what we've seen so far is an Objective-C type that could
4010 // be a receiver of a class message, this may be a class message send with
4011 // the initial opening bracket '[' missing. Add appropriate completions.
4012 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004013 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004014 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004015 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4016 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004017 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004018 (S->getFlags() & Scope::DeclScope) != 0 &&
4019 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004020 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4021 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004022 ParsedType T = DS.getRepAsType();
4023 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004024 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004025 }
4026
Douglas Gregor56ccce02010-08-24 04:59:56 +00004027 // Note that we intentionally suppress macro results here, since we do not
4028 // encourage using macros to produce the names of entities.
4029
Fangrui Song050229d2018-11-24 00:14:31 +00004030 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004031 Results.data(), Results.size());
4032}
4033
Douglas Gregor68762e72010-08-23 21:17:50 +00004034struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004035 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4036 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004037 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004038 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004039
Douglas Gregor68762e72010-08-23 21:17:50 +00004040 QualType PreferredType;
4041 bool IntegralConstantExpression;
4042 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004043 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004044 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004045};
4046
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004047/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004048/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004049void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004050 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004051 ResultBuilder Results(
4052 *this, CodeCompleter->getAllocator(),
4053 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004054 CodeCompletionContext(
4055 Data.IsParenthesized
4056 ? CodeCompletionContext::CCC_ParenthesizedExpression
4057 : CodeCompletionContext::CCC_Expression,
4058 Data.PreferredType));
4059 auto PCC =
4060 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004061 if (Data.ObjCCollection)
4062 Results.setFilter(&ResultBuilder::IsObjCCollection);
4063 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004064 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004065 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004066 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4067 else
4068 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004069
4070 if (!Data.PreferredType.isNull())
4071 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004072
Douglas Gregor68762e72010-08-23 21:17:50 +00004073 // Ignore any declarations that we were told that we don't care about.
4074 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4075 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004076
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004077 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004078 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004079 CodeCompleter->includeGlobals(),
4080 CodeCompleter->loadExternal());
4081
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004082 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004083 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004084 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004085
Douglas Gregor55b037b2010-07-08 20:55:51 +00004086 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00004087 if (!Data.PreferredType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00004088 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4089 Data.PreferredType->isMemberPointerType() ||
4090 Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004091
Fangrui Song050229d2018-11-24 00:14:31 +00004092 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004093 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004094 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004095
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004096 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004097 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4098 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00004099 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4100 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004101}
4102
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004103void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4104 bool IsParenthesized) {
4105 return CodeCompleteExpression(
4106 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004107}
4108
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004109void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4110 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004111 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004112 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004113 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004114 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004115}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004116
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004117/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004118/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004119typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004120
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004121/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004122static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4123 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4124 if (Interface->hasDefinition())
4125 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004126
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004127 return Interface;
4128 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004129
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004130 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4131 if (Protocol->hasDefinition())
4132 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004133
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004134 return Protocol;
4135 }
4136 return Container;
4137}
4138
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004139/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004140/// declaration \p BD.
4141static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4142 CodeCompletionBuilder &Builder,
4143 const NamedDecl *BD,
4144 const FunctionTypeLoc &BlockLoc,
4145 const FunctionProtoTypeLoc &BlockProtoLoc) {
4146 Builder.AddResultTypeChunk(
4147 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4148 Policy, Builder.getAllocator()));
4149
4150 AddTypedNameChunk(Context, Policy, BD, Builder);
4151 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4152
4153 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4154 Builder.AddPlaceholderChunk("...");
4155 } else {
4156 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4157 if (I)
4158 Builder.AddChunk(CodeCompletionString::CK_Comma);
4159
4160 // Format the placeholder string.
4161 std::string PlaceholderStr =
4162 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4163
4164 if (I == N - 1 && BlockProtoLoc &&
4165 BlockProtoLoc.getTypePtr()->isVariadic())
4166 PlaceholderStr += ", ...";
4167
4168 // Add the placeholder string.
4169 Builder.AddPlaceholderChunk(
4170 Builder.getAllocator().CopyString(PlaceholderStr));
4171 }
4172 }
4173
4174 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4175}
4176
Fangrui Song050229d2018-11-24 00:14:31 +00004177static void
4178AddObjCProperties(const CodeCompletionContext &CCContext,
4179 ObjCContainerDecl *Container, bool AllowCategories,
4180 bool AllowNullaryMethods, DeclContext *CurContext,
4181 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4182 bool IsBaseExprStatement = false,
4183 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004184 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004185
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004186 // Retrieve the definition.
4187 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004188
Douglas Gregor9291bad2009-11-18 01:29:26 +00004189 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004190 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004191 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004192 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004193
Alex Lorenzbaef8022016-11-09 13:43:18 +00004194 // FIXME: Provide block invocation completion for non-statement
4195 // expressions.
4196 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4197 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004198 Result R = Result(P, Results.getBasePriority(P), nullptr);
4199 if (!InOriginalClass)
4200 setInBaseClass(R);
4201 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004202 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004203 }
4204
4205 // Block setter and invocation completion is provided only when we are able
4206 // to find the FunctionProtoTypeLoc with parameter names for the block.
4207 FunctionTypeLoc BlockLoc;
4208 FunctionProtoTypeLoc BlockProtoLoc;
4209 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4210 BlockProtoLoc);
4211 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004212 Result R = Result(P, Results.getBasePriority(P), nullptr);
4213 if (!InOriginalClass)
4214 setInBaseClass(R);
4215 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004216 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004217 }
4218
4219 // The default completion result for block properties should be the block
4220 // invocation completion when the base expression is a statement.
4221 CodeCompletionBuilder Builder(Results.getAllocator(),
4222 Results.getCodeCompletionTUInfo());
4223 AddObjCBlockCall(Container->getASTContext(),
4224 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4225 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004226 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4227 if (!InOriginalClass)
4228 setInBaseClass(R);
4229 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004230
4231 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004232 // statement and the block property is mutable.
4233 if (!P->isReadOnly()) {
4234 CodeCompletionBuilder Builder(Results.getAllocator(),
4235 Results.getCodeCompletionTUInfo());
4236 AddResultTypeChunk(Container->getASTContext(),
4237 getCompletionPrintingPolicy(Results.getSema()), P,
4238 CCContext.getBaseType(), Builder);
4239 Builder.AddTypedTextChunk(
4240 Results.getAllocator().CopyString(P->getName()));
4241 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004242
Alex Lorenzbaef8022016-11-09 13:43:18 +00004243 std::string PlaceholderStr = formatBlockPlaceholder(
4244 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4245 BlockProtoLoc, /*SuppressBlockName=*/true);
4246 // Add the placeholder string.
4247 Builder.AddPlaceholderChunk(
4248 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004249
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004250 // When completing blocks properties that return void the default
4251 // property completion result should show up before the setter,
4252 // otherwise the setter completion should show up before the default
4253 // property completion, as we normally want to use the result of the
4254 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004255 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004256 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004257 Results.getBasePriority(P) +
4258 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4259 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004260 : -CCD_BlockPropertySetter));
4261 if (!InOriginalClass)
4262 setInBaseClass(R);
4263 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004264 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004265 };
4266
4267 if (IsClassProperty) {
4268 for (const auto *P : Container->class_properties())
4269 AddProperty(P);
4270 } else {
4271 for (const auto *P : Container->instance_properties())
4272 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004273 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004274
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004275 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004276 if (AllowNullaryMethods) {
4277 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004278 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004279 // Adds a method result
4280 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4281 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4282 if (!Name)
4283 return;
4284 if (!AddedProperties.insert(Name).second)
4285 return;
4286 CodeCompletionBuilder Builder(Results.getAllocator(),
4287 Results.getCodeCompletionTUInfo());
4288 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4289 Builder.AddTypedTextChunk(
4290 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004291 Result R = Result(Builder.TakeString(), M,
4292 CCP_MemberDeclaration + CCD_MethodAsProperty);
4293 if (!InOriginalClass)
4294 setInBaseClass(R);
4295 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004296 };
4297
4298 if (IsClassProperty) {
4299 for (const auto *M : Container->methods()) {
4300 // Gather the class method that can be used as implicit property
4301 // getters. Methods with arguments or methods that return void aren't
4302 // added to the results as they can't be used as a getter.
4303 if (!M->getSelector().isUnarySelector() ||
4304 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4305 continue;
4306 AddMethod(M);
4307 }
4308 } else {
4309 for (auto *M : Container->methods()) {
4310 if (M->getSelector().isUnarySelector())
4311 AddMethod(M);
4312 }
Douglas Gregor95147142011-05-05 15:50:42 +00004313 }
4314 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004315
Douglas Gregor9291bad2009-11-18 01:29:26 +00004316 // Add properties in referenced protocols.
4317 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004318 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004319 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004320 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004321 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004322 /*InOriginalClass*/ false);
4323 } else if (ObjCInterfaceDecl *IFace =
4324 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004325 if (AllowCategories) {
4326 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004327 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004328 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004329 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004330 IsBaseExprStatement, IsClassProperty,
4331 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004332 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004333
Douglas Gregor9291bad2009-11-18 01:29:26 +00004334 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004335 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004336 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004337 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004338 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004339 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004340
Douglas Gregor9291bad2009-11-18 01:29:26 +00004341 // Look in the superclass.
4342 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004343 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004344 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004345 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004346 /*InOriginalClass*/ false);
4347 } else if (const auto *Category =
4348 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004349 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004350 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004351 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004352 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004353 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004354 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004355 }
4356}
4357
Fangrui Song050229d2018-11-24 00:14:31 +00004358static void
4359AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
4360 Scope *S, QualType BaseType, RecordDecl *RD,
4361 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004362 // Indicate that we are performing a member access, and the cv-qualifiers
4363 // for the base object type.
4364 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4365
4366 // Access to a C/C++ class, struct, or union.
4367 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004368 std::vector<FixItHint> FixIts;
4369 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004370 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004371 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004372 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004373 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004374 /*IncludeDependentBases=*/true,
4375 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004376
4377 if (SemaRef.getLangOpts().CPlusPlus) {
4378 if (!Results.empty()) {
4379 // The "template" keyword can follow "->" or "." in the grammar.
4380 // However, we only want to suggest the template keyword if something
4381 // is dependent.
4382 bool IsDependent = BaseType->isDependentType();
4383 if (!IsDependent) {
4384 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4385 if (DeclContext *Ctx = DepScope->getEntity()) {
4386 IsDependent = Ctx->isDependentContext();
4387 break;
4388 }
4389 }
4390
4391 if (IsDependent)
4392 Results.AddResult(CodeCompletionResult("template"));
4393 }
4394 }
4395}
4396
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004397void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004398 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004399 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004400 bool IsBaseExprStatement,
4401 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004402 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004403 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004404
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004405 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4406 if (ConvertedBase.isInvalid())
4407 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004408 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4409
4410 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004411
4412 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004413 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004414 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004415 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004416
Douglas Gregor21325842011-07-07 16:03:39 +00004417 if (IsArrow) {
4418 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004419 } else {
4420 if (ConvertedBaseType->isObjCObjectPointerType() ||
4421 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004422 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004423 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004424 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4425 }
4426 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004427
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004428 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004429 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004430 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004431 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004432 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004433
Fangrui Song050229d2018-11-24 00:14:31 +00004434 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4435 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004436 if (!Base)
4437 return false;
4438
4439 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4440 if (ConvertedBase.isInvalid())
4441 return false;
4442 Base = ConvertedBase.get();
4443
4444 QualType BaseType = Base->getType();
4445
4446 if (IsArrow) {
4447 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4448 BaseType = Ptr->getPointeeType();
4449 else if (BaseType->isObjCObjectPointerType())
4450 /*Do nothing*/;
4451 else
4452 return false;
4453 }
4454
4455 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4456 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4457 Record->getDecl(),
4458 std::move(AccessOpFixIt));
4459 } else if (const auto *TST =
4460 BaseType->getAs<TemplateSpecializationType>()) {
4461 TemplateName TN = TST->getTemplateName();
4462 if (const auto *TD =
4463 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4464 CXXRecordDecl *RD = TD->getTemplatedDecl();
4465 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4466 std::move(AccessOpFixIt));
4467 }
4468 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4469 if (auto *RD = ICNT->getDecl())
4470 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4471 std::move(AccessOpFixIt));
4472 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4473 // Objective-C property reference.
4474 AddedPropertiesSet AddedProperties;
4475
4476 if (const ObjCObjectPointerType *ObjCPtr =
4477 BaseType->getAsObjCInterfacePointerType()) {
4478 // Add property results based on our interface.
4479 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4480 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4481 /*AllowNullaryMethods=*/true, CurContext,
4482 AddedProperties, Results, IsBaseExprStatement);
4483 }
4484
4485 // Add properties from the protocols in a qualified interface.
4486 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4487 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4488 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004489 IsBaseExprStatement, /*IsClassProperty*/ false,
4490 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004491 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4492 (!IsArrow && BaseType->isObjCObjectType())) {
4493 // Objective-C instance variable access.
4494 ObjCInterfaceDecl *Class = nullptr;
4495 if (const ObjCObjectPointerType *ObjCPtr =
4496 BaseType->getAs<ObjCObjectPointerType>())
4497 Class = ObjCPtr->getInterfaceDecl();
4498 else
4499 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4500
4501 // Add all ivars from this class and its superclasses.
4502 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004503 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004504 Results.setFilter(&ResultBuilder::IsObjCIvar);
4505 LookupVisibleDecls(
4506 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4507 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4508 }
4509 }
4510
4511 // FIXME: How do we cope with isa?
4512 return true;
4513 };
4514
Douglas Gregor9291bad2009-11-18 01:29:26 +00004515 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004516
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004517 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4518 if (CodeCompleter->includeFixIts()) {
4519 const CharSourceRange OpRange =
4520 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4521 CompletionSucceded |= DoCompletion(
4522 OtherOpBase, !IsArrow,
4523 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004524 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004525
Douglas Gregor9291bad2009-11-18 01:29:26 +00004526 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004527
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004528 if (!CompletionSucceded)
4529 return;
4530
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004531 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004532 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4533 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004534}
4535
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004536void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4537 IdentifierInfo &ClassName,
4538 SourceLocation ClassNameLoc,
4539 bool IsBaseExprStatement) {
4540 IdentifierInfo *ClassNamePtr = &ClassName;
4541 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4542 if (!IFace)
4543 return;
4544 CodeCompletionContext CCContext(
4545 CodeCompletionContext::CCC_ObjCPropertyAccess);
4546 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4547 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4548 &ResultBuilder::IsMember);
4549 Results.EnterNewScope();
4550 AddedPropertiesSet AddedProperties;
4551 AddObjCProperties(CCContext, IFace, true,
4552 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4553 Results, IsBaseExprStatement,
4554 /*IsClassProperty=*/true);
4555 Results.ExitScope();
4556 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4557 Results.data(), Results.size());
4558}
4559
Faisal Vali090da2d2018-01-01 18:23:28 +00004560void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004561 if (!CodeCompleter)
4562 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004563
4564 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004565 enum CodeCompletionContext::Kind ContextKind =
4566 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004567 switch ((DeclSpec::TST)TagSpec) {
4568 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004569 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004570 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004571 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004572
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004573 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004574 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004575 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004576 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004577
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004578 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004579 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004580 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004581 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004582 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004583 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004584
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004585 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004586 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004587 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004588
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004589 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4590 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004591 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004592
4593 // First pass: look for tags.
4594 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004595 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004596 CodeCompleter->includeGlobals(),
4597 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004598
Douglas Gregor39982192010-08-15 06:18:01 +00004599 if (CodeCompleter->includeGlobals()) {
4600 // Second pass: look for nested name specifiers.
4601 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004602 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4603 CodeCompleter->includeGlobals(),
4604 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004605 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004606
Douglas Gregor0ac41382010-09-23 23:01:17 +00004607 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004608 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004609}
4610
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004611static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4612 const LangOptions &LangOpts) {
4613 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4614 Results.AddResult("const");
4615 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4616 Results.AddResult("volatile");
4617 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4618 Results.AddResult("restrict");
4619 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4620 Results.AddResult("_Atomic");
4621 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4622 Results.AddResult("__unaligned");
4623}
4624
Douglas Gregor28c78432010-08-27 17:35:51 +00004625void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004626 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004627 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004628 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004629 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004630 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004631 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004632 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004633 Results.data(), Results.size());
4634}
4635
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004636void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4637 const VirtSpecifiers *VS) {
4638 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4639 CodeCompleter->getCodeCompletionTUInfo(),
4640 CodeCompletionContext::CCC_TypeQualifiers);
4641 Results.EnterNewScope();
4642 AddTypeQualifierResults(DS, Results, LangOpts);
4643 if (LangOpts.CPlusPlus11) {
4644 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004645 if (D.getContext() == DeclaratorContext::MemberContext &&
4646 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004647 if (!VS || !VS->isFinalSpecified())
4648 Results.AddResult("final");
4649 if (!VS || !VS->isOverrideSpecified())
4650 Results.AddResult("override");
4651 }
4652 }
4653 Results.ExitScope();
4654 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4655 Results.data(), Results.size());
4656}
4657
Benjamin Kramer72dae622016-02-18 15:30:24 +00004658void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4659 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4660}
4661
Douglas Gregord328d572009-09-21 18:10:23 +00004662void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004663 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004664 return;
John McCall5939b162011-08-06 07:30:58 +00004665
Richard Smithef6c43d2018-07-26 18:41:30 +00004666 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004667 // Condition expression might be invalid, do not continue in this case.
4668 if (!Switch->getCond())
4669 return;
John McCall5939b162011-08-06 07:30:58 +00004670 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4671 if (!type->isEnumeralType()) {
4672 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004673 Data.IntegralConstantExpression = true;
4674 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004675 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004676 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004677
Douglas Gregord328d572009-09-21 18:10:23 +00004678 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004679 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004680 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004681 if (EnumDecl *Def = Enum->getDefinition())
4682 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004683
Douglas Gregord328d572009-09-21 18:10:23 +00004684 // Determine which enumerators we have already seen in the switch statement.
4685 // FIXME: Ideally, we would also be able to look *past* the code-completion
4686 // token, in case we are code-completing in the middle of the switch and not
4687 // at the end. However, we aren't able to do so at the moment.
4688 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004689 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004690 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004691 SC = SC->getNextSwitchCase()) {
4692 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4693 if (!Case)
4694 continue;
4695
4696 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004697 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4698 if (auto *Enumerator =
4699 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004700 // We look into the AST of the case statement to determine which
4701 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004702 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004703 // values of each enumerator. However, value-based approach would not
4704 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004705 // template are type- and value-dependent.
4706 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004707
Douglas Gregorf2510672009-09-21 19:57:38 +00004708 // If this is a qualified-id, keep track of the nested-name-specifier
4709 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004710 //
4711 // switch (TagD.getKind()) {
4712 // case TagDecl::TK_enum:
4713 // break;
4714 // case XXX
4715 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004716 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004717 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4718 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004719 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004720 }
4721 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004722
David Blaikiebbafb8a2012-03-11 07:00:24 +00004723 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004724 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004725 // qualify the names of the enumerators that we suggest, because they
4726 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004727 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004728 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004729
Douglas Gregord328d572009-09-21 18:10:23 +00004730 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004731 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004732 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004733 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004734 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004735 for (auto *E : Enum->enumerators()) {
4736 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004737 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004738
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004739 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004740 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004741 }
4742 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004743
Douglas Gregor21325842011-07-07 16:03:39 +00004744 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004745 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004746 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004747 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4748 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004749}
4750
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004751static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004752 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004753 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004754
4755 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004756 if (!Args[I])
4757 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004758
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004759 return false;
4760}
4761
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004762typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4763
Fangrui Song050229d2018-11-24 00:14:31 +00004764static void mergeCandidatesWithResults(
4765 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
4766 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004767 if (!CandidateSet.empty()) {
4768 // Sort the overload candidate set by placing the best overloads first.
4769 std::stable_sort(
4770 CandidateSet.begin(), CandidateSet.end(),
4771 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004772 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4773 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004774 });
4775
4776 // Add the remaining viable overload candidates as code-completion results.
Fangrui Song050229d2018-11-24 00:14:31 +00004777 for (OverloadCandidate &Candidate : CandidateSet) {
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004778 if (Candidate.Function && Candidate.Function->isDeleted())
4779 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004780 if (Candidate.Viable)
4781 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004782 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004783 }
4784}
4785
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004786/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004787/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004788static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00004789 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004790
4791 // Given the overloads 'Candidates' for a function call matching all arguments
4792 // up to N, return the type of the Nth parameter if it is the same for all
4793 // overload candidates.
4794 QualType ParamType;
4795 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00004796 if (const auto *FType = Candidate.getFunctionType())
4797 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004798 if (N < Proto->getNumParams()) {
4799 if (ParamType.isNull())
4800 ParamType = Proto->getParamType(N);
4801 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00004802 ParamType.getNonReferenceType(),
4803 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004804 // Otherwise return a default-constructed QualType.
4805 return QualType();
4806 }
4807 }
4808
4809 return ParamType;
4810}
4811
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004812static QualType
4813ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4814 MutableArrayRef<ResultCandidate> Candidates,
4815 unsigned CurrentArg, SourceLocation OpenParLoc) {
4816 if (Candidates.empty())
4817 return QualType();
4818 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4819 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4820 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004821}
4822
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004823QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4824 ArrayRef<Expr *> Args,
4825 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004826 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004827 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004828
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004829 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004830 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004831 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4832 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004833 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004834 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004835
John McCall57500772009-12-16 12:17:52 +00004836 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004837 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004838 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004839
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004840 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004841
John McCall57500772009-12-16 12:17:52 +00004842 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004843 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004844 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004845 /*PartialOverloading=*/true);
4846 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4847 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4848 if (UME->hasExplicitTemplateArgs()) {
4849 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4850 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004851 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004852
4853 // Add the base as first argument (use a nullptr if the base is implicit).
4854 SmallVector<Expr *, 12> ArgExprs(
4855 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004856 ArgExprs.append(Args.begin(), Args.end());
4857 UnresolvedSet<8> Decls;
4858 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004859 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004860 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4861 /*SuppressUsedConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00004862 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004863 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004864 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004865 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004866 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00004867 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004868 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004869 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004870 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004871 !FD->getType()->getAs<FunctionProtoType>())
4872 Results.push_back(ResultCandidate(FD));
4873 else
4874 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4875 Args, CandidateSet,
4876 /*SuppressUsedConversions=*/false,
4877 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004878
4879 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4880 // If expression's type is CXXRecordDecl, it may overload the function
4881 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004882 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004883 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00004884 DeclarationName OpName =
4885 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004886 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4887 LookupQualifiedName(R, DC);
4888 R.suppressDiagnostics();
4889 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4890 ArgExprs.append(Args.begin(), Args.end());
4891 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4892 /*ExplicitArgs=*/nullptr,
4893 /*SuppressUsedConversions=*/false,
4894 /*PartialOverloading=*/true);
4895 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004896 } else {
4897 // Lastly we check whether expression's type is function pointer or
4898 // function.
4899 QualType T = NakedFn->getType();
4900 if (!T->getPointeeType().isNull())
4901 T = T->getPointeeType();
4902
4903 if (auto FP = T->getAs<FunctionProtoType>()) {
4904 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00004905 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004906 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004907 Results.push_back(ResultCandidate(FP));
4908 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004909 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004910 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004911 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004912 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004913 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004914 QualType ParamType =
4915 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4916 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004917}
4918
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004919QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4920 SourceLocation Loc,
4921 ArrayRef<Expr *> Args,
4922 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004923 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004924 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004925
4926 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004927 CXXRecordDecl *RD =
4928 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004929 if (!RD)
4930 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004931
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004932 // FIXME: Provide support for member initializers.
4933 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004934
4935 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4936
Fangrui Song050229d2018-11-24 00:14:31 +00004937 for (NamedDecl *C : LookupConstructors(RD)) {
4938 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
4939 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
4940 CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004941 /*SuppressUsedConversions=*/false,
4942 /*PartialOverloading=*/true);
Fangrui Song050229d2018-11-24 00:14:31 +00004943 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4944 AddTemplateOverloadCandidate(
4945 FTD, DeclAccessPair::make(FTD, C->getAccess()),
4946 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
4947 /*SuppressUsedConversions=*/false,
4948 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004949 }
4950 }
4951
4952 SmallVector<ResultCandidate, 8> Results;
4953 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004954 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004955}
4956
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004957QualType Sema::ProduceCtorInitMemberSignatureHelp(
4958 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4959 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4960 if (!CodeCompleter)
4961 return QualType();
4962
4963 CXXConstructorDecl *Constructor =
4964 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4965 if (!Constructor)
4966 return QualType();
4967 // FIXME: Add support for Base class constructors as well.
4968 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4969 Constructor->getParent(), SS, TemplateTypeTy, II))
4970 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4971 MemberDecl->getLocation(), ArgExprs,
4972 OpenParLoc);
4973 return QualType();
4974}
4975
John McCall48871652010-08-21 09:40:31 +00004976void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4977 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004978 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004979 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004980 return;
4981 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004982
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00004983 CodeCompleteExpressionData Data;
4984 Data.PreferredType = VD->getType();
4985 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
4986 Data.IgnoreDecls.push_back(VD);
4987
4988 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004989}
4990
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004991void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004992 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004993 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004994 mapCodeCompletionContext(*this, PCC_Statement));
4995 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4996 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004997
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004998 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4999 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005000 CodeCompleter->includeGlobals(),
5001 CodeCompleter->loadExternal());
5002
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005003 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005004
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005005 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005006 CodeCompletionBuilder Builder(Results.getAllocator(),
5007 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005008 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005009 if (Results.includeCodePatterns()) {
5010 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5011 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5012 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5013 Builder.AddPlaceholderChunk("statements");
5014 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5015 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5016 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005017 Results.AddResult(Builder.TakeString());
5018
5019 // "else if" block
5020 Builder.AddTypedTextChunk("else");
5021 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5022 Builder.AddTextChunk("if");
5023 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5024 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005025 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005026 Builder.AddPlaceholderChunk("condition");
5027 else
5028 Builder.AddPlaceholderChunk("expression");
5029 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005030 if (Results.includeCodePatterns()) {
5031 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5032 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5033 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5034 Builder.AddPlaceholderChunk("statements");
5035 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5036 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5037 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005038 Results.AddResult(Builder.TakeString());
5039
5040 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005041
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005042 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005043 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005044
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005045 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005046 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005047
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005048 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005049 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005050}
5051
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005052void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005053 bool EnteringContext, QualType BaseType) {
Eric Liu06d34022017-12-12 11:35:46 +00005054 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005055 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005056
Eric Liu06d34022017-12-12 11:35:46 +00005057 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5058 // "a::b::" is not corresponding to any context/namespace in the AST), since
5059 // it can be useful for global code completion which have information about
5060 // contexts/symbols that are not in the AST.
5061 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005062 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00005063 CC.setCXXScopeSpecifier(SS);
Eric Liu206740e2019-02-21 11:22:58 +00005064 // As SS is invalid, we try to collect accessible contexts from the current
5065 // scope with a dummy lookup so that the completion consumer can try to
5066 // guess what the specified scope is.
5067 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5068 CodeCompleter->getCodeCompletionTUInfo(), CC);
5069 if (S->getEntity()) {
5070 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5071 BaseType);
5072 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5073 /*IncludeGlobalScope=*/false,
5074 /*LoadExternal=*/false);
5075 }
5076 HandleCodeCompleteResults(this, CodeCompleter,
5077 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005078 return;
5079 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005080 // Always pretend to enter a context to ensure that a dependent type
5081 // resolves to a dependent record.
5082 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005083 if (!Ctx)
5084 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005085
5086 // Try to instantiate any non-dependent declaration contexts before
5087 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005088 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005089 return;
5090
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005091 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005092 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005093 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005094 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005095
Douglas Gregor3545ff42009-09-21 16:56:56 +00005096 // The "template" keyword can follow "::" in the grammar, but only
5097 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005098 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005099 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005100 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005101
5102 // Add calls to overridden virtual functions, if there are any.
5103 //
5104 // FIXME: This isn't wonderful, because we don't know whether we're actually
5105 // in a context that permits expressions. This is a general issue with
5106 // qualified-id completions.
5107 if (!EnteringContext)
5108 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005109 Results.ExitScope();
5110
Eric Liufead6ae2017-12-13 10:26:49 +00005111 if (CodeCompleter->includeNamespaceLevelDecls() ||
5112 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005113 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005114 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5115 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005116 /*IncludeDependentBases=*/true,
5117 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005118 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005119
Eric Liu06d34022017-12-12 11:35:46 +00005120 auto CC = Results.getCompletionContext();
5121 CC.setCXXScopeSpecifier(SS);
5122
5123 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
5124 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005125}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005126
5127void Sema::CodeCompleteUsing(Scope *S) {
5128 if (!CodeCompleter)
5129 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005130
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005131 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005132 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005133 // This can be both a using alias or using
5134 // declaration, in the former we expect a new name and a
5135 // symbol in the latter case.
5136 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005137 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005138 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005139
Douglas Gregor3545ff42009-09-21 16:56:56 +00005140 // If we aren't in class scope, we could see the "namespace" keyword.
5141 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005142 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005143
5144 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005145 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005146 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005147 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005148 CodeCompleter->includeGlobals(),
5149 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005150 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005151
5152 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5153 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005154}
5155
5156void Sema::CodeCompleteUsingDirective(Scope *S) {
5157 if (!CodeCompleter)
5158 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005159
Douglas Gregor3545ff42009-09-21 16:56:56 +00005160 // After "using namespace", we expect to see a namespace name or namespace
5161 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005162 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005163 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005164 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005165 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005166 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005167 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005168 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005169 CodeCompleter->includeGlobals(),
5170 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005171 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005172 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5173 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005174}
5175
Fangrui Song050229d2018-11-24 00:14:31 +00005176void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005177 if (!CodeCompleter)
5178 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005179
Ted Kremenekc37877d2013-10-08 17:08:03 +00005180 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005181 if (!S->getParent())
5182 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005183
Fangrui Song050229d2018-11-24 00:14:31 +00005184 bool SuppressedGlobalResults =
5185 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005186
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005187 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005188 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005189 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005190 ? CodeCompletionContext::CCC_Namespace
5191 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005192 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005193
Douglas Gregor0ac41382010-09-23 23:01:17 +00005194 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005195 // We only want to see those namespaces that have already been defined
5196 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005197 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005198 // definition of each namespace.
5199 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005200 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005201 NS(Ctx->decls_begin()),
5202 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005203 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005204 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005205
5206 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005207 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005208 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005209 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005210 NS = OrigToLatest.begin(),
5211 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005212 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005213 Results.AddResult(
5214 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5215 nullptr),
5216 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005217 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005218 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005219
Fangrui Song050229d2018-11-24 00:14:31 +00005220 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5221 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005222}
5223
Fangrui Song050229d2018-11-24 00:14:31 +00005224void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005225 if (!CodeCompleter)
5226 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005227
Douglas Gregor3545ff42009-09-21 16:56:56 +00005228 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005229 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005230 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005231 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005232 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005233 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005234 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005235 CodeCompleter->includeGlobals(),
5236 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005237 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5238 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005239}
5240
Douglas Gregorc811ede2009-09-18 20:05:18 +00005241void Sema::CodeCompleteOperatorName(Scope *S) {
5242 if (!CodeCompleter)
5243 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005244
John McCall276321a2010-08-25 06:19:51 +00005245 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005246 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005247 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005248 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005249 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005250 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005251
Douglas Gregor3545ff42009-09-21 16:56:56 +00005252 // Add the names of overloadable operators.
Fangrui Song050229d2018-11-24 00:14:31 +00005253#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5254 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005255 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005256#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005257
Douglas Gregor3545ff42009-09-21 16:56:56 +00005258 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005259 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005260 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005261 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005262 CodeCompleter->includeGlobals(),
5263 CodeCompleter->loadExternal());
5264
Douglas Gregor3545ff42009-09-21 16:56:56 +00005265 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005266 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005267 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005268
5269 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5270 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005271}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005272
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005273void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005274 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005275 if (!ConstructorD)
5276 return;
5277
5278 AdjustDeclIfTemplate(ConstructorD);
5279
Fangrui Song050229d2018-11-24 00:14:31 +00005280 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005281 if (!Constructor)
5282 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005283
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005284 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005285 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005286 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005287 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005288
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005289 // Fill in any already-initialized fields or base classes.
5290 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5291 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005292 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005293 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005294 InitializedBases.insert(Context.getCanonicalType(
5295 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005296 else
Fangrui Song050229d2018-11-24 00:14:31 +00005297 InitializedFields.insert(
5298 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005299 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005300
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005301 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005302 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005303 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005304 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005305
5306 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5307 CodeCompletionBuilder Builder(Results.getAllocator(),
5308 Results.getCodeCompletionTUInfo());
5309 Builder.AddTypedTextChunk(Name);
5310 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005311 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005312 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005313 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005314 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5315 Builder);
5316 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5317 return Builder.TakeString();
5318 };
5319 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5320 const NamedDecl *ND) {
5321 CodeCompletionBuilder Builder(Results.getAllocator(),
5322 Results.getCodeCompletionTUInfo());
5323 Builder.AddTypedTextChunk(Name);
5324 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5325 Builder.AddPlaceholderChunk(Type);
5326 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5327 if (ND) {
5328 auto CCR = CodeCompletionResult(
5329 Builder.TakeString(), ND,
5330 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5331 if (isa<FieldDecl>(ND))
5332 CCR.CursorKind = CXCursor_MemberRef;
5333 return Results.AddResult(CCR);
5334 }
5335 return Results.AddResult(CodeCompletionResult(
5336 Builder.TakeString(),
5337 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5338 };
5339 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5340 const char *Name, const FieldDecl *FD) {
5341 if (!RD)
5342 return AddDefaultCtorInit(Name,
5343 FD ? Results.getAllocator().CopyString(
5344 FD->getType().getAsString(Policy))
5345 : Name,
5346 FD);
5347 auto Ctors = getConstructors(Context, RD);
5348 if (Ctors.begin() == Ctors.end())
5349 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005350 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005351 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5352 CCR.CursorKind = getCursorKindForDecl(Ctor);
5353 Results.AddResult(CCR);
5354 }
5355 };
5356 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5357 const char *BaseName =
5358 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5359 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5360 AddCtorsWithName(
5361 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5362 BaseName, nullptr);
5363 };
5364 auto AddField = [&](const FieldDecl *FD) {
5365 const char *FieldName =
5366 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5367 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5368 AddCtorsWithName(
5369 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5370 FieldName, FD);
5371 };
5372
Aaron Ballman574705e2014-03-13 15:41:46 +00005373 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005374 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5375 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005376 SawLastInitializer =
5377 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5378 Context.hasSameUnqualifiedType(
5379 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005380 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005381 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005382
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005383 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005384 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005385 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005386
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005387 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005388 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005389 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5390 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005391 SawLastInitializer =
5392 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5393 Context.hasSameUnqualifiedType(
5394 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005395 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005396 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005397
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005398 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005399 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005400 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005401
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005402 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005403 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005404 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5405 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005406 SawLastInitializer = !Initializers.empty() &&
5407 Initializers.back()->isAnyMemberInitializer() &&
5408 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005409 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005410 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005411
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005412 if (!Field->getDeclName())
5413 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005414
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005415 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005416 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005417 }
5418 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005419
Douglas Gregor0ac41382010-09-23 23:01:17 +00005420 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005421 Results.data(), Results.size());
5422}
5423
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005424/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005425static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005426 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005427 if (!DC)
5428 return false;
5429
5430 return DC->isFileContext();
5431}
5432
5433void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5434 bool AfterAmpersand) {
5435 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005436 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005437 CodeCompletionContext::CCC_Other);
5438 Results.EnterNewScope();
5439
5440 // Note what has already been captured.
5441 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5442 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005443 for (const auto &C : Intro.Captures) {
5444 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005445 IncludedThis = true;
5446 continue;
5447 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005448
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005449 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005450 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005451
Douglas Gregord8c61782012-02-15 15:34:24 +00005452 // Look for other capturable variables.
5453 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005454 for (const auto *D : S->decls()) {
5455 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005456 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005457 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005458
David Blaikie82e95a32014-11-19 07:49:47 +00005459 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005460 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005461 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005462 }
5463 }
5464
5465 // Add 'this', if it would be valid.
5466 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5467 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005468
Douglas Gregord8c61782012-02-15 15:34:24 +00005469 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005470
Douglas Gregord8c61782012-02-15 15:34:24 +00005471 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5472 Results.data(), Results.size());
5473}
5474
James Dennett596e4752012-06-14 03:11:41 +00005475/// Macro that optionally prepends an "@" to the string literal passed in via
5476/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005477#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005478
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005479static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005480 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005481 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005482 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005483 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005484
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005485 CodeCompletionBuilder Builder(Results.getAllocator(),
5486 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005487 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005488 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005489 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5491 Builder.AddPlaceholderChunk("property");
5492 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005493
Douglas Gregorf1934162010-01-13 21:24:21 +00005494 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005495 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005496 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5497 Builder.AddPlaceholderChunk("property");
5498 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005499 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005500}
5501
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005502static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005503 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005504 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005505
Douglas Gregorf1934162010-01-13 21:24:21 +00005506 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005507 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005508
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005509 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005510 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005511 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005512
Douglas Gregorf1934162010-01-13 21:24:21 +00005513 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005514 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005515
Douglas Gregorf1934162010-01-13 21:24:21 +00005516 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005517 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005518 }
5519}
5520
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005521static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005522 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005523 CodeCompletionBuilder Builder(Results.getAllocator(),
5524 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005525
Douglas Gregorf1934162010-01-13 21:24:21 +00005526 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005527 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005528 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5529 Builder.AddPlaceholderChunk("name");
5530 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005531
Douglas Gregorf4c33342010-05-28 00:22:41 +00005532 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005533 // @interface name
5534 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005535 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005536 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005537 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5538 Builder.AddPlaceholderChunk("class");
5539 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005540
Douglas Gregorf4c33342010-05-28 00:22:41 +00005541 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005542 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005543 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5544 Builder.AddPlaceholderChunk("protocol");
5545 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005546
Douglas Gregorf4c33342010-05-28 00:22:41 +00005547 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005548 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005549 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5550 Builder.AddPlaceholderChunk("class");
5551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005552 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005553
Douglas Gregorf1934162010-01-13 21:24:21 +00005554 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005555 Builder.AddTypedTextChunk(
5556 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005557 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5558 Builder.AddPlaceholderChunk("alias");
5559 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5560 Builder.AddPlaceholderChunk("class");
5561 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005562
5563 if (Results.getSema().getLangOpts().Modules) {
5564 // @import name
5565 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5566 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5567 Builder.AddPlaceholderChunk("module");
5568 Results.AddResult(Result(Builder.TakeString()));
5569 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005570}
5571
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005572void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005573 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005574 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005575 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005576 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005577 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005578 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005579 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005580 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005581 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005582 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005583 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005584 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5585 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005586}
5587
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005588static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005589 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005590 CodeCompletionBuilder Builder(Results.getAllocator(),
5591 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005592
5593 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005594 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005595 if (Results.getSema().getLangOpts().CPlusPlus ||
5596 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005597 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005598 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005599 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005600 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5601 Builder.AddPlaceholderChunk("type-name");
5602 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5603 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005604
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005605 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005606 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005607 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005608 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5609 Builder.AddPlaceholderChunk("protocol-name");
5610 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5611 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005612
5613 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005614 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005615 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005616 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5617 Builder.AddPlaceholderChunk("selector");
5618 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5619 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005620
5621 // @"string"
5622 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005623 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005624 Builder.AddPlaceholderChunk("string");
5625 Builder.AddTextChunk("\"");
5626 Results.AddResult(Result(Builder.TakeString()));
5627
Douglas Gregor951de302012-07-17 23:24:47 +00005628 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005629 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005630 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005631 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005632 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5633 Results.AddResult(Result(Builder.TakeString()));
5634
Douglas Gregor951de302012-07-17 23:24:47 +00005635 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005636 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005637 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005638 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005639 Builder.AddChunk(CodeCompletionString::CK_Colon);
5640 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5641 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005642 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5643 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005644
Douglas Gregor951de302012-07-17 23:24:47 +00005645 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005646 Builder.AddResultTypeChunk("id");
5647 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005648 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005649 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5650 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005651}
5652
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005653static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005654 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005655 CodeCompletionBuilder Builder(Results.getAllocator(),
5656 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005657
Douglas Gregorf4c33342010-05-28 00:22:41 +00005658 if (Results.includeCodePatterns()) {
5659 // @try { statements } @catch ( declaration ) { statements } @finally
5660 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005661 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005662 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5663 Builder.AddPlaceholderChunk("statements");
5664 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5665 Builder.AddTextChunk("@catch");
5666 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5667 Builder.AddPlaceholderChunk("parameter");
5668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5669 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5670 Builder.AddPlaceholderChunk("statements");
5671 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5672 Builder.AddTextChunk("@finally");
5673 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5674 Builder.AddPlaceholderChunk("statements");
5675 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5676 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005677 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005678
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005679 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005680 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005681 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5682 Builder.AddPlaceholderChunk("expression");
5683 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005684
Douglas Gregorf4c33342010-05-28 00:22:41 +00005685 if (Results.includeCodePatterns()) {
5686 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005687 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005688 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5690 Builder.AddPlaceholderChunk("expression");
5691 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5692 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5693 Builder.AddPlaceholderChunk("statements");
5694 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5695 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005696 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005697}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005698
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005699static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005700 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005701 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005702 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5703 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5704 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005705 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005706 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005707}
5708
5709void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005710 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005711 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005712 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005713 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005714 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005715 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005716 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5717 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005718}
5719
5720void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005721 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005722 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005723 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005724 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005725 AddObjCStatementResults(Results, false);
5726 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005727 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005728 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5729 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005730}
5731
5732void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005733 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005734 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005735 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005736 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005737 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005738 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005739 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5740 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005741}
5742
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005743/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005744/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005745static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005746 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005747 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005748 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005749
Bill Wendling44426052012-12-20 19:22:21 +00005750 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005751
Douglas Gregore6078da2009-11-19 00:14:45 +00005752 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005753 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5754 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005755 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005756
Jordan Rose53cb2f32012-08-20 20:01:13 +00005757 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00005758 unsigned AssignCopyRetMask =
5759 Attributes &
5760 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
5761 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
5762 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
5763 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005764 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005765 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005766 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005767 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5768 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005769 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005770
Douglas Gregore6078da2009-11-19 00:14:45 +00005771 return false;
5772}
5773
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005774void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005775 if (!CodeCompleter)
5776 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005777
Bill Wendling44426052012-12-20 19:22:21 +00005778 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005779
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005780 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005781 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005782 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005783 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005784 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005785 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005786 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005787 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005788 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005789 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5790 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005791 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005792 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005793 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005794 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005795 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005796 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005797 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005798 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005799 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005800 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005801 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005802 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005803
5804 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005805 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005806 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005807 Results.AddResult(CodeCompletionResult("weak"));
5808
Bill Wendling44426052012-12-20 19:22:21 +00005809 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005810 CodeCompletionBuilder Setter(Results.getAllocator(),
5811 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005812 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005813 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005814 Setter.AddPlaceholderChunk("method");
5815 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005816 }
Bill Wendling44426052012-12-20 19:22:21 +00005817 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005818 CodeCompletionBuilder Getter(Results.getAllocator(),
5819 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005820 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005821 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005822 Getter.AddPlaceholderChunk("method");
5823 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005824 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005825 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5826 Results.AddResult(CodeCompletionResult("nonnull"));
5827 Results.AddResult(CodeCompletionResult("nullable"));
5828 Results.AddResult(CodeCompletionResult("null_unspecified"));
5829 Results.AddResult(CodeCompletionResult("null_resettable"));
5830 }
Steve Naroff936354c2009-10-08 21:55:05 +00005831 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005832 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5833 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005834}
Steve Naroffeae65032009-11-07 02:08:14 +00005835
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005836/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005837/// via code completion.
5838enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005839 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5840 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00005841 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005842};
5843
Fangrui Song050229d2018-11-24 00:14:31 +00005844static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005845 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005846 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005847 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005848 if (NumSelIdents > Sel.getNumArgs())
5849 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005850
Douglas Gregor67c692c2010-08-26 15:07:07 +00005851 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00005852 case MK_Any:
5853 break;
5854 case MK_ZeroArgSelector:
5855 return Sel.isUnarySelector();
5856 case MK_OneArgSelector:
5857 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005858 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005859
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005860 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5861 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005862
Douglas Gregor67c692c2010-08-26 15:07:07 +00005863 for (unsigned I = 0; I != NumSelIdents; ++I)
5864 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5865 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005866
Douglas Gregor67c692c2010-08-26 15:07:07 +00005867 return true;
5868}
5869
Douglas Gregorc8537c52009-11-19 07:41:15 +00005870static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5871 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005872 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005873 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005874 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005875 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005876}
Douglas Gregor1154e272010-09-16 16:06:31 +00005877
Fangrui Song050229d2018-11-24 00:14:31 +00005878/// A set of selectors, which is used to avoid introducing multiple
5879/// completions with the same selector into the result set.
5880typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00005881
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005882/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005883/// container to the set of results.
5884///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005885/// The container will be a class, protocol, category, or implementation of
5886/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005887/// the superclasses of classes along with their categories, protocols, and
5888/// implementations.
5889///
5890/// \param Container the container in which we'll look to find methods.
5891///
James Dennett596e4752012-06-14 03:11:41 +00005892/// \param WantInstanceMethods Whether to add instance methods (only); if
5893/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005894///
5895/// \param CurContext the context in which we're performing the lookup that
5896/// finds methods.
5897///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005898/// \param AllowSameLength Whether we allow a method to be added to the list
5899/// when it has the same number of parameters as we have selector identifiers.
5900///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005901/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005902static void AddObjCMethods(ObjCContainerDecl *Container,
5903 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005904 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005905 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005906 VisitedSelectorSet &Selectors, bool AllowSameLength,
5907 ResultBuilder &Results, bool InOriginalClass = true,
5908 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005909 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005910 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005911 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005912 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00005913 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005914 // The instance methods on the root class can be messaged via the
5915 // metaclass.
5916 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005917 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005918 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005919 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005920 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005921 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005922
David Blaikie82e95a32014-11-19 07:49:47 +00005923 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005924 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005925
5926 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005927 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005928 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005929 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00005930 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00005931 Results.MaybeAddResult(R, CurContext);
5932 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005933 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005934
Douglas Gregorf37c9492010-09-16 15:34:59 +00005935 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005936 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005937 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00005938 const ObjCList<ObjCProtocolDecl> &Protocols =
5939 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005940 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005941 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005942 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005943 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5944 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005945 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005946 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005947
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005948 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005949 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005950
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005951 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005952 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005953 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5954 Selectors, AllowSameLength, Results, false, IsRootClass);
5955
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005956 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00005957 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005958 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005959 CurContext, Selectors, AllowSameLength, Results,
5960 InOriginalClass, IsRootClass);
5961
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005962 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00005963 const ObjCList<ObjCProtocolDecl> &Protocols =
5964 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005965 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5966 E = Protocols.end();
5967 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005968 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5969 Selectors, AllowSameLength, Results, false, IsRootClass);
5970
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005971 // Add methods in category implementations.
5972 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005973 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5974 Selectors, AllowSameLength, Results, InOriginalClass,
5975 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005976 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005977
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005978 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005979 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005980 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005981 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5982 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5983 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005984
5985 // Add methods in our implementation, if any.
5986 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005987 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5988 Selectors, AllowSameLength, Results, InOriginalClass,
5989 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005990}
5991
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005992void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005993 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005994 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005995 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00005996 if (ObjCCategoryDecl *Category =
5997 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005998 Class = Category->getClassInterface();
5999
6000 if (!Class)
6001 return;
6002 }
6003
6004 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006005 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006006 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006007 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006008 Results.EnterNewScope();
6009
Douglas Gregor1154e272010-09-16 16:06:31 +00006010 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006011 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006012 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006013 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006014 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6015 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006016}
6017
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006018void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006019 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006020 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006021 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006022 if (ObjCCategoryDecl *Category =
6023 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006024 Class = Category->getClassInterface();
6025
6026 if (!Class)
6027 return;
6028 }
6029
6030 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006031 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006032 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006033 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006034 Results.EnterNewScope();
6035
Douglas Gregor1154e272010-09-16 16:06:31 +00006036 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006037 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6038 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006039
6040 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006041 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6042 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006043}
6044
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006045void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6046 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006047 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006048 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006049 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006050 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006051
Douglas Gregor99fa2642010-08-24 01:06:58 +00006052 // Add context-sensitive, Objective-C parameter-passing keywords.
6053 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006054 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006055 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6056 Results.AddResult("in");
6057 Results.AddResult("inout");
6058 AddedInOut = true;
6059 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006060 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006061 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6062 Results.AddResult("out");
6063 if (!AddedInOut)
6064 Results.AddResult("inout");
6065 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006066 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006067 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6068 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006069 Results.AddResult("bycopy");
6070 Results.AddResult("byref");
6071 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006072 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006073 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6074 Results.AddResult("nonnull");
6075 Results.AddResult("nullable");
6076 Results.AddResult("null_unspecified");
6077 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006078
6079 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006080 // identifier IBAction refers to a macro, provide a completion item for
6081 // an action, e.g.,
6082 // IBAction)<#selector#>:(id)sender
6083 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006084 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006085 CodeCompletionBuilder Builder(Results.getAllocator(),
6086 Results.getCodeCompletionTUInfo(),
6087 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006088 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006089 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006090 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006091 Builder.AddChunk(CodeCompletionString::CK_Colon);
6092 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006093 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006094 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006095 Builder.AddTextChunk("sender");
6096 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6097 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006098
6099 // If we're completing the return type, provide 'instancetype'.
6100 if (!IsParameter) {
6101 Results.AddResult(CodeCompletionResult("instancetype"));
6102 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006103
Douglas Gregor99fa2642010-08-24 01:06:58 +00006104 // Add various builtin type names and specifiers.
6105 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6106 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006107
Douglas Gregor99fa2642010-08-24 01:06:58 +00006108 // Add the various type names
6109 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6110 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6111 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006112 CodeCompleter->includeGlobals(),
6113 CodeCompleter->loadExternal());
6114
Douglas Gregor99fa2642010-08-24 01:06:58 +00006115 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006116 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006117
Eric Liuf5ba09f2018-07-04 10:01:18 +00006118 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006119 Results.data(), Results.size());
6120}
6121
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006122/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006123/// that it has some more-specific class type based on knowledge of
6124/// common uses of Objective-C. This routine returns that class type,
6125/// or NULL if no better result could be determined.
6126static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006127 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006128 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006129 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006130
6131 Selector Sel = Msg->getSelector();
6132 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006133 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006134
6135 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6136 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006137 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006138
6139 ObjCMethodDecl *Method = Msg->getMethodDecl();
6140 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006141 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006142
6143 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006144 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006145 switch (Msg->getReceiverKind()) {
6146 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006147 if (const ObjCObjectType *ObjType =
6148 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006149 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006150 break;
6151
6152 case ObjCMessageExpr::Instance: {
6153 QualType T = Msg->getInstanceReceiver()->getType();
6154 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6155 IFace = Ptr->getInterfaceDecl();
6156 break;
6157 }
6158
6159 case ObjCMessageExpr::SuperInstance:
6160 case ObjCMessageExpr::SuperClass:
6161 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006162 }
6163
6164 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006165 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006166
6167 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6168 if (Method->isInstanceMethod())
6169 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006170 .Case("retain", IFace)
6171 .Case("strong", IFace)
6172 .Case("autorelease", IFace)
6173 .Case("copy", IFace)
6174 .Case("copyWithZone", IFace)
6175 .Case("mutableCopy", IFace)
6176 .Case("mutableCopyWithZone", IFace)
6177 .Case("awakeFromCoder", IFace)
6178 .Case("replacementObjectFromCoder", IFace)
6179 .Case("class", IFace)
6180 .Case("classForCoder", IFace)
6181 .Case("superclass", Super)
6182 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006183
6184 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006185 .Case("new", IFace)
6186 .Case("alloc", IFace)
6187 .Case("allocWithZone", IFace)
6188 .Case("class", IFace)
6189 .Case("superclass", Super)
6190 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006191}
6192
Douglas Gregor6fc04132010-08-27 15:10:57 +00006193// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006194// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006195// function.
6196///
6197/// \param S The semantic analysis object.
6198///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006199/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006200/// the "super" keyword. Otherwise, we just need to provide the arguments.
6201///
6202/// \param SelIdents The identifiers in the selector that have already been
6203/// provided as arguments for a send to "super".
6204///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006205/// \param Results The set of results to augment.
6206///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006207/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006208/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006209static ObjCMethodDecl *
6210AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6211 ArrayRef<IdentifierInfo *> SelIdents,
6212 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006213 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6214 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006215 return nullptr;
6216
Douglas Gregor6fc04132010-08-27 15:10:57 +00006217 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6218 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006219 return nullptr;
6220
Douglas Gregor6fc04132010-08-27 15:10:57 +00006221 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006222 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006223 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6224 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006225 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006226 CurMethod->isInstanceMethod());
6227
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006228 // Check in categories or class extensions.
6229 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006230 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006231 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006232 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006233 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006234 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006235 }
6236 }
6237
Douglas Gregor6fc04132010-08-27 15:10:57 +00006238 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006239 return nullptr;
6240
Douglas Gregor6fc04132010-08-27 15:10:57 +00006241 // Check whether the superclass method has the same signature.
6242 if (CurMethod->param_size() != SuperMethod->param_size() ||
6243 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006244 return nullptr;
6245
Douglas Gregor6fc04132010-08-27 15:10:57 +00006246 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006247 CurPEnd = CurMethod->param_end(),
6248 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006249 CurP != CurPEnd; ++CurP, ++SuperP) {
6250 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006251 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006252 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006253 return nullptr;
6254
Douglas Gregor6fc04132010-08-27 15:10:57 +00006255 // Make sure we have a parameter name to forward!
6256 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006257 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006258 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006259
Douglas Gregor6fc04132010-08-27 15:10:57 +00006260 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006261 CodeCompletionBuilder Builder(Results.getAllocator(),
6262 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006263
Douglas Gregor6fc04132010-08-27 15:10:57 +00006264 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006265 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006266 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006267
6268 // If we need the "super" keyword, add it (plus some spacing).
6269 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006270 Builder.AddTypedTextChunk("super");
6271 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006272 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006273
Douglas Gregor6fc04132010-08-27 15:10:57 +00006274 Selector Sel = CurMethod->getSelector();
6275 if (Sel.isUnarySelector()) {
6276 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006277 Builder.AddTextChunk(
6278 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006279 else
Fangrui Song050229d2018-11-24 00:14:31 +00006280 Builder.AddTypedTextChunk(
6281 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006282 } else {
6283 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6284 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006285 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006286 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006287
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006288 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006289 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006290 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006291 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006292 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006293 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006294 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006295 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006296 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006297 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006298 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006299 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006300 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006301 }
6302 }
6303 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006304
Douglas Gregor78254c82012-03-27 23:34:16 +00006305 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6306 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006307 return SuperMethod;
6308}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006309
Douglas Gregora817a192010-05-27 23:06:34 +00006310void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006311 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006312 ResultBuilder Results(
6313 *this, CodeCompleter->getAllocator(),
6314 CodeCompleter->getCodeCompletionTUInfo(),
6315 CodeCompletionContext::CCC_ObjCMessageReceiver,
6316 getLangOpts().CPlusPlus11
6317 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6318 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006319
Douglas Gregora817a192010-05-27 23:06:34 +00006320 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6321 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006322 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006323 CodeCompleter->includeGlobals(),
6324 CodeCompleter->loadExternal());
6325
Douglas Gregora817a192010-05-27 23:06:34 +00006326 // If we are in an Objective-C method inside a class that has a superclass,
6327 // add "super" as an option.
6328 if (ObjCMethodDecl *Method = getCurMethodDecl())
6329 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006330 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006331 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006332
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006333 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006334 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006335
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006336 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006337 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006338
Douglas Gregora817a192010-05-27 23:06:34 +00006339 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006340
Douglas Gregora817a192010-05-27 23:06:34 +00006341 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006342 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006343 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006344 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006345}
6346
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006347void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006348 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006349 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006350 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006351 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6352 // Figure out which interface we're in.
6353 CDecl = CurMethod->getClassInterface();
6354 if (!CDecl)
6355 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006356
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006357 // Find the superclass of this class.
6358 CDecl = CDecl->getSuperClass();
6359 if (!CDecl)
6360 return;
6361
6362 if (CurMethod->isInstanceMethod()) {
6363 // We are inside an instance method, which means that the message
6364 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006365 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006366 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006367 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006368 }
6369
6370 // Fall through to send to the superclass in CDecl.
6371 } else {
6372 // "super" may be the name of a type or variable. Figure out which
6373 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006374 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006375 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006376 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6377 // "super" names an interface. Use it.
6378 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006379 if (const ObjCObjectType *Iface =
6380 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006381 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006382 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6383 // "super" names an unresolved type; we can't be more specific.
6384 } else {
6385 // Assume that "super" names some kind of value and parse that way.
6386 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006387 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006388 UnqualifiedId id;
6389 id.setIdentifier(Super, SuperLoc);
Fangrui Song050229d2018-11-24 00:14:31 +00006390 ExprResult SuperExpr =
6391 ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006392 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006393 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006394 }
6395
6396 // Fall through
6397 }
6398
John McCallba7bf592010-08-24 05:47:05 +00006399 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006400 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006401 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006402 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006403 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006404 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006405}
6406
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006407/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006408/// send, determine the preferred type (if any) for that argument expression.
6409static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6410 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006411 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006412 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006413
Douglas Gregor74661272010-09-21 00:03:25 +00006414 QualType PreferredType;
6415 unsigned BestPriority = CCP_Unlikely * 2;
6416 Result *ResultsData = Results.data();
6417 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6418 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006419 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006420 isa<ObjCMethodDecl>(R.Declaration)) {
6421 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006422 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006423 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006424 QualType MyPreferredType =
6425 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006426 if (R.Priority < BestPriority || PreferredType.isNull()) {
6427 BestPriority = R.Priority;
6428 PreferredType = MyPreferredType;
6429 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6430 MyPreferredType)) {
6431 PreferredType = QualType();
6432 }
6433 }
6434 }
6435 }
6436 }
6437
6438 return PreferredType;
6439}
6440
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006441static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006442 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006443 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006444 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006445 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006446 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006447 ObjCInterfaceDecl *CDecl = nullptr;
6448
Douglas Gregor8ce33212009-11-17 17:59:40 +00006449 // If the given name refers to an interface type, retrieve the
6450 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006451 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006452 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006453 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006454 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6455 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006456 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006457
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006458 // Add all of the factory methods in this Objective-C class, its protocols,
6459 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006460 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006461
6462 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006463 // completion.
6464 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006465 if (ObjCMethodDecl *SuperMethod =
6466 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006467 Results.Ignore(SuperMethod);
6468 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006469
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006470 // If we're inside an Objective-C method definition, prefer its selector to
6471 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006472 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006473 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006474
Douglas Gregor1154e272010-09-16 16:06:31 +00006475 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006476 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006477 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6478 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006479 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006480 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006481
Douglas Gregord720daf2010-04-06 17:30:22 +00006482 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006483 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006484 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006485 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006486 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006487 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006488 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006489 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006490 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006491
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006492 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006493 }
6494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006495
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006496 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006497 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006498 M != MEnd; ++M) {
6499 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006500 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006501 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006502 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006503
Nico Weber2e0c8f72014-12-27 03:58:08 +00006504 Result R(MethList->getMethod(),
6505 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006506 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006507 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006508 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006509 }
6510 }
6511 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006512
6513 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006514}
Douglas Gregor6285f752010-04-06 16:40:00 +00006515
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006516void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006517 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006518 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006519 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006520
Douglas Gregor63745d52011-07-21 01:05:26 +00006521 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006522
Fangrui Song050229d2018-11-24 00:14:31 +00006523 ResultBuilder Results(
6524 *this, CodeCompleter->getAllocator(),
6525 CodeCompleter->getCodeCompletionTUInfo(),
6526 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6527 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006528
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006529 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006530 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006531
6532 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006533 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006534 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006535 // code-complete the expression using the corresponding parameter type as
6536 // our preferred type, improving completion results.
6537 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006538 QualType PreferredType =
6539 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006540 if (PreferredType.isNull())
6541 CodeCompleteOrdinaryName(S, PCC_Expression);
6542 else
6543 CodeCompleteExpression(S, PreferredType);
6544 return;
6545 }
6546
Fangrui Song050229d2018-11-24 00:14:31 +00006547 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006548 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006549}
6550
Richard Trieu2bd04012011-09-09 02:00:50 +00006551void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006552 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006553 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006554 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006555 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006556
Steve Naroffeae65032009-11-07 02:08:14 +00006557 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006558
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006559 // If necessary, apply function/array conversion to the receiver.
6560 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006561 if (RecExpr) {
6562 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6563 if (Conv.isInvalid()) // conversion failed. bail.
6564 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006565 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006566 }
Fangrui Song050229d2018-11-24 00:14:31 +00006567 QualType ReceiverType = RecExpr
6568 ? RecExpr->getType()
6569 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006570 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006571 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006572
Douglas Gregordc520b02010-11-08 21:12:30 +00006573 // If we're messaging an expression with type "id" or "Class", check
6574 // whether we know something special about the receiver that allows
6575 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006576 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006577 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6578 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006579 return CodeCompleteObjCClassMessage(
6580 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6581 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006582
Fangrui Song050229d2018-11-24 00:14:31 +00006583 ReceiverType =
6584 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006585 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006586 } else if (RecExpr && getLangOpts().CPlusPlus) {
6587 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6588 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006589 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006590 ReceiverType = RecExpr->getType();
6591 }
6592 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006593
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006594 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006595 ResultBuilder Results(
6596 *this, CodeCompleter->getAllocator(),
6597 CodeCompleter->getCodeCompletionTUInfo(),
6598 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6599 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006600
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006601 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006602
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006603 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006604 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006605 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006606 if (ObjCMethodDecl *SuperMethod =
6607 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006608 Results.Ignore(SuperMethod);
6609 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006610
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006611 // If we're inside an Objective-C method definition, prefer its selector to
6612 // others.
6613 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6614 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006615
Douglas Gregor1154e272010-09-16 16:06:31 +00006616 // Keep track of the selectors we've already added.
6617 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006618
Douglas Gregora3329fa2009-11-18 00:06:18 +00006619 // Handle messages to Class. This really isn't a message to an instance
6620 // method, so we treat it the same way we would treat a message send to a
6621 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006622 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006623 ReceiverType->isObjCQualifiedClassType()) {
6624 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6625 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006626 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6627 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006628 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006629 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006630 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006631 else if (const ObjCObjectPointerType *QualID =
6632 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006633 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006634 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006635 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6636 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006637 }
6638 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006639 else if (const ObjCObjectPointerType *IFacePtr =
6640 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006641 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006642 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006643 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006644
Douglas Gregora3329fa2009-11-18 00:06:18 +00006645 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006646 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006647 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6648 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006649 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006650 // Handle messages to "id".
6651 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006652 // We're messaging "id", so provide all instance methods we know
6653 // about as code-completion results.
6654
6655 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006656 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006657 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006658 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6659 I != N; ++I) {
6660 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006661 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006662 continue;
6663
Sebastian Redl75d8a322010-08-02 23:18:59 +00006664 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006665 }
6666 }
6667
Sebastian Redl75d8a322010-08-02 23:18:59 +00006668 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6669 MEnd = MethodPool.end();
6670 M != MEnd; ++M) {
6671 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006672 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006673 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006674 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006675
Nico Weber2e0c8f72014-12-27 03:58:08 +00006676 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006677 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006678
Nico Weber2e0c8f72014-12-27 03:58:08 +00006679 Result R(MethList->getMethod(),
6680 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006681 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006682 R.AllParametersAreInformative = false;
6683 Results.MaybeAddResult(R, CurContext);
6684 }
6685 }
6686 }
Steve Naroffeae65032009-11-07 02:08:14 +00006687 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006688
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006689 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006690 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006691 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006692 // code-complete the expression using the corresponding parameter type as
6693 // our preferred type, improving completion results.
6694 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006695 QualType PreferredType =
6696 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006697 if (PreferredType.isNull())
6698 CodeCompleteOrdinaryName(S, PCC_Expression);
6699 else
6700 CodeCompleteExpression(S, PreferredType);
6701 return;
6702 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006703
Fangrui Song050229d2018-11-24 00:14:31 +00006704 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6705 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006706}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006707
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006708void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006709 DeclGroupPtrTy IterationVar) {
6710 CodeCompleteExpressionData Data;
6711 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006712
Douglas Gregor68762e72010-08-23 21:17:50 +00006713 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006714 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006715 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6716 if (*I)
6717 Data.IgnoreDecls.push_back(*I);
6718 }
6719 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006720
Douglas Gregor68762e72010-08-23 21:17:50 +00006721 CodeCompleteExpression(S, Data);
6722}
6723
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006724void Sema::CodeCompleteObjCSelector(Scope *S,
6725 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006726 // If we have an external source, load the entire class method
6727 // pool from the AST file.
6728 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00006729 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
6730 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006731 Selector Sel = ExternalSource->GetExternalSelector(I);
6732 if (Sel.isNull() || MethodPool.count(Sel))
6733 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006734
Douglas Gregor67c692c2010-08-26 15:07:07 +00006735 ReadMethodPool(Sel);
6736 }
6737 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006738
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006739 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006740 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006741 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006742 Results.EnterNewScope();
6743 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006744 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006745 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006746
Douglas Gregor67c692c2010-08-26 15:07:07 +00006747 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006748 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006749 continue;
6750
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006751 CodeCompletionBuilder Builder(Results.getAllocator(),
6752 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006753 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006754 Builder.AddTypedTextChunk(
6755 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006756 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006757 continue;
6758 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006759
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006760 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006761 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006762 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006763 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006764 Builder.AddInformativeChunk(
6765 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006766 Accumulator.clear();
6767 }
6768 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006769
Benjamin Kramer632500c2011-07-26 16:59:25 +00006770 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006771 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006772 }
Fangrui Song050229d2018-11-24 00:14:31 +00006773 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006774 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006775 }
6776 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006777
6778 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006779 Results.data(), Results.size());
6780}
6781
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006782/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006783/// (translation unit) context.
6784static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006785 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006786 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006787 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006788
Aaron Ballman629afae2014-03-07 19:56:05 +00006789 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006790 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006791 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006792 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00006793 Results.AddResult(
6794 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
6795 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006796 }
6797}
6798
Craig Topper883dd332015-12-24 23:58:11 +00006799void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00006800 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006801 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006802 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006803 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006804
Chandler Carruthede11632016-11-04 06:06:50 +00006805 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006806 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006807
Douglas Gregora3b23b02010-12-09 21:44:02 +00006808 // Tell the result set to ignore all of the protocols we have
6809 // already seen.
6810 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006811 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00006812 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006813 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006814
Douglas Gregora3b23b02010-12-09 21:44:02 +00006815 // Add all protocols.
6816 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6817 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006818
Douglas Gregora3b23b02010-12-09 21:44:02 +00006819 Results.ExitScope();
6820 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006821
6822 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6823 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006824}
6825
6826void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006827 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006828 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006829 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006830
Chandler Carruthede11632016-11-04 06:06:50 +00006831 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006832 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006833
Douglas Gregora3b23b02010-12-09 21:44:02 +00006834 // Add all protocols.
6835 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6836 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006837
Douglas Gregora3b23b02010-12-09 21:44:02 +00006838 Results.ExitScope();
6839 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006840
6841 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6842 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006843}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006844
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006845/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006846/// the given (translation unit) context.
6847static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6848 bool OnlyForwardDeclarations,
6849 bool OnlyUnimplemented,
6850 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006851 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006852
Aaron Ballman629afae2014-03-07 19:56:05 +00006853 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006854 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006855 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006856 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006857 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00006858 Results.AddResult(
6859 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
6860 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006861 }
6862}
6863
Eric Liuf5ba09f2018-07-04 10:01:18 +00006864void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006865 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006866 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006867 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006868 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006869
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006870 if (CodeCompleter->includeGlobals()) {
6871 // Add all classes.
6872 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6873 false, Results);
6874 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006875
Douglas Gregor49c22a72009-11-18 16:26:39 +00006876 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006877
Eric Liuf5ba09f2018-07-04 10:01:18 +00006878 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6879 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006880}
6881
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006882void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006883 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006884 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006885 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006886 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006887 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006888
Douglas Gregor49c22a72009-11-18 16:26:39 +00006889 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00006890 NamedDecl *CurClass =
6891 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006892 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006893 Results.Ignore(CurClass);
6894
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006895 if (CodeCompleter->includeGlobals()) {
6896 // Add all classes.
6897 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6898 false, Results);
6899 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006900
Douglas Gregor49c22a72009-11-18 16:26:39 +00006901 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006902
Eric Liuf5ba09f2018-07-04 10:01:18 +00006903 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6904 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006905}
6906
Eric Liuf5ba09f2018-07-04 10:01:18 +00006907void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006908 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006909 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006910 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006911 Results.EnterNewScope();
6912
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006913 if (CodeCompleter->includeGlobals()) {
6914 // Add all unimplemented classes.
6915 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6916 true, Results);
6917 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006918
Douglas Gregor49c22a72009-11-18 16:26:39 +00006919 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006920
Eric Liuf5ba09f2018-07-04 10:01:18 +00006921 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6922 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006923}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006924
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006925void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006926 IdentifierInfo *ClassName,
6927 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006928 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006929
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006930 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006931 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006932 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006933
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006934 // Ignore any categories we find that have already been implemented by this
6935 // interface.
6936 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00006937 NamedDecl *CurClass =
6938 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
6939 if (ObjCInterfaceDecl *Class =
6940 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006941 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006942 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006943 }
6944
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006945 // Add all of the categories we know about.
6946 Results.EnterNewScope();
6947 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006948 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006949 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006950 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00006951 Results.AddResult(
6952 Result(Category, Results.getBasePriority(Category), nullptr),
6953 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006954 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006955
6956 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6957 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006958}
6959
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006960void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006961 IdentifierInfo *ClassName,
6962 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006963 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006964
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006965 // Find the corresponding interface. If we couldn't find the interface, the
6966 // program itself is ill-formed. However, we'll try to be helpful still by
6967 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00006968 NamedDecl *CurClass =
6969 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006970 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6971 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006972 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006973
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006974 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006975 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006976 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006977
6978 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006979 // declarations in this class and any of its superclasses, except for
6980 // already-implemented categories in the class itself.
6981 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6982 Results.EnterNewScope();
6983 bool IgnoreImplemented = true;
6984 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006985 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006986 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006987 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006988 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6989 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006990 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006991
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006992 Class = Class->getSuperClass();
6993 IgnoreImplemented = false;
6994 }
6995 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006996
6997 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6998 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006999}
Douglas Gregor5d649882009-11-18 22:32:06 +00007000
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007001void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007002 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007003 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007004 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007005
7006 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007007 ObjCContainerDecl *Container =
7008 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7009 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7010 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007011 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007012
7013 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007014 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007015 for (const auto *D : Container->decls())
7016 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007017 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007018
Douglas Gregor5d649882009-11-18 22:32:06 +00007019 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007020 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007021 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007022 if (ObjCImplementationDecl *ClassImpl =
7023 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007024 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007025 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007026 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007027 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007028 AddObjCProperties(CCContext,
7029 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007030 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007031 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007032 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007033
7034 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7035 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007036}
7037
Fangrui Song050229d2018-11-24 00:14:31 +00007038void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7039 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007040 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007041 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007042 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007043 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007044
7045 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007046 ObjCContainerDecl *Container =
7047 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7048 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7049 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007050 return;
7051
Douglas Gregor5d649882009-11-18 22:32:06 +00007052 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007053 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007054 if (ObjCImplementationDecl *ClassImpl =
7055 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007056 Class = ClassImpl->getClassInterface();
7057 else
Fangrui Song050229d2018-11-24 00:14:31 +00007058 Class = cast<ObjCCategoryImplDecl>(Container)
7059 ->getCategoryDecl()
7060 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007061
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007062 // Determine the type of the property we're synthesizing.
7063 QualType PropertyType = Context.getObjCIdType();
7064 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007065 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7066 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007067 PropertyType =
7068 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007069
7070 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007071 Results.setPreferredType(PropertyType);
7072 }
7073 }
7074
Douglas Gregor5d649882009-11-18 22:32:06 +00007075 // Add all of the instance variables in this class and its superclasses.
7076 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007077 bool SawSimilarlyNamedIvar = false;
7078 std::string NameWithPrefix;
7079 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007080 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007081 std::string NameWithSuffix = PropertyName->getName().str();
7082 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007083 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007084 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007085 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007086 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7087 CurContext, nullptr, false);
7088
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007089 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007090 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007091 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007092 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007093 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007094 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007095
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007096 // Reduce the priority of this result by one, to give it a slight
7097 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007098 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007099 Results.data()[Results.size() - 1].Kind ==
7100 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007101 Results.data()[Results.size() - 1].Declaration == Ivar)
7102 Results.data()[Results.size() - 1].Priority--;
7103 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007104 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007105 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007106
Douglas Gregor331faa02011-04-18 14:13:53 +00007107 if (!SawSimilarlyNamedIvar) {
7108 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007109 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007110 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007111 typedef CodeCompletionResult Result;
7112 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007113 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007114 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007115
Douglas Gregor75acd922011-09-27 23:30:47 +00007116 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007117 Builder.AddResultTypeChunk(
7118 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007119 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007120 Results.AddResult(
7121 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007122 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007123
Douglas Gregor5d649882009-11-18 22:32:06 +00007124 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007125
7126 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7127 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007128}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007129
Douglas Gregor416b5752010-08-25 01:08:01 +00007130// Mapping from selectors to the methods that implement that selector, along
7131// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007132typedef llvm::DenseMap<Selector,
7133 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7134 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007135
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007136/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007137/// (and its superclasses, protocols, etc.) that meet the given
7138/// criteria. Insert those methods into the map of known methods,
7139/// indexed by selector so they can be easily found.
7140static void FindImplementableMethods(ASTContext &Context,
7141 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007142 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007143 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007144 KnownMethodsMap &KnownMethods,
7145 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007146 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007147 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007148 if (!IFace->hasDefinition())
7149 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007150
7151 IFace = IFace->getDefinition();
7152 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007153
Fangrui Song050229d2018-11-24 00:14:31 +00007154 const ObjCList<ObjCProtocolDecl> &Protocols =
7155 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007156 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007157 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007158 I != E; ++I)
7159 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007160 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007161
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007162 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007163 for (auto *Cat : IFace->visible_categories()) {
7164 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007165 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007166 }
7167
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007168 // Visit the superclass.
7169 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007170 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007171 WantInstanceMethods, ReturnType, KnownMethods,
7172 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007173 }
7174
7175 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7176 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007177 const ObjCList<ObjCProtocolDecl> &Protocols =
7178 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007179 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007180 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007181 I != E; ++I)
7182 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007183 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007184
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007185 // If this category is the original class, jump to the interface.
7186 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007187 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007188 WantInstanceMethods, ReturnType, KnownMethods,
7189 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007190 }
7191
7192 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007193 // Make sure we have a definition; that's what we'll walk.
7194 if (!Protocol->hasDefinition())
7195 return;
7196 Protocol = Protocol->getDefinition();
7197 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007198
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007199 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007200 const ObjCList<ObjCProtocolDecl> &Protocols =
7201 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007202 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007203 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007204 I != E; ++I)
7205 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7206 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007207 }
7208
7209 // Add methods in this container. This operation occurs last because
7210 // we want the methods from this container to override any methods
7211 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007212 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007213 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007214 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007215 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007216 continue;
7217
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007218 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007219 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007220 }
7221 }
7222}
7223
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007224/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007225/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007226static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007227 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007228 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007229 CodeCompletionBuilder &Builder) {
7230 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007231 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007232 if (!Quals.empty())
7233 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007234 Builder.AddTextChunk(
7235 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007236 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7237}
7238
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007239/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007240/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007241static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007242 if (!Class)
7243 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007244
Douglas Gregor669a25a2011-02-17 00:22:45 +00007245 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7246 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007247
Douglas Gregor669a25a2011-02-17 00:22:45 +00007248 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7249}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007250
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007251/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007252/// Key-Value Observing (KVO).
7253static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7254 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007255 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007256 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007257 ResultBuilder &Results) {
7258 IdentifierInfo *PropName = Property->getIdentifier();
7259 if (!PropName || PropName->getLength() == 0)
7260 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007261
Douglas Gregor75acd922011-09-27 23:30:47 +00007262 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7263
Douglas Gregor669a25a2011-02-17 00:22:45 +00007264 // Builder that will create each code completion.
7265 typedef CodeCompletionResult Result;
7266 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007267 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007268
Douglas Gregor669a25a2011-02-17 00:22:45 +00007269 // The selector table.
7270 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007271
Douglas Gregor669a25a2011-02-17 00:22:45 +00007272 // The property name, copied into the code completion allocation region
7273 // on demand.
7274 struct KeyHolder {
7275 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007276 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007277 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007278
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007279 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007280 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007281
Douglas Gregor669a25a2011-02-17 00:22:45 +00007282 operator const char *() {
7283 if (CopiedKey)
7284 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007285
Douglas Gregor669a25a2011-02-17 00:22:45 +00007286 return CopiedKey = Allocator.CopyString(Key);
7287 }
7288 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007289
Douglas Gregor669a25a2011-02-17 00:22:45 +00007290 // The uppercased name of the property name.
7291 std::string UpperKey = PropName->getName();
7292 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007293 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007294
Fangrui Song050229d2018-11-24 00:14:31 +00007295 bool ReturnTypeMatchesProperty =
7296 ReturnType.isNull() ||
7297 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7298 Property->getType());
7299 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007300
Douglas Gregor669a25a2011-02-17 00:22:45 +00007301 // Add the normal accessor -(type)key.
7302 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007303 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007304 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7305 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007306 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7307 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007308
Douglas Gregor669a25a2011-02-17 00:22:45 +00007309 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007310 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007311 CXCursor_ObjCInstanceMethodDecl));
7312 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007313
Douglas Gregor669a25a2011-02-17 00:22:45 +00007314 // If we have an integral or boolean property (or the user has provided
7315 // an integral or boolean return type), add the accessor -(type)isKey.
7316 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007317 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007318 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007319 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7320 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007321 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007322 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007323 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7324 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007325 if (ReturnType.isNull()) {
7326 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7327 Builder.AddTextChunk("BOOL");
7328 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7329 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007330
Fangrui Song050229d2018-11-24 00:14:31 +00007331 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007332 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007333 CXCursor_ObjCInstanceMethodDecl));
7334 }
7335 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007336
Douglas Gregor669a25a2011-02-17 00:22:45 +00007337 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007338 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007339 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007340 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007341 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007342 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007343 if (ReturnType.isNull()) {
7344 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7345 Builder.AddTextChunk("void");
7346 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7347 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007348
Fangrui Song050229d2018-11-24 00:14:31 +00007349 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007350 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007351 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7352 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007353 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007354 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007355 CXCursor_ObjCInstanceMethodDecl));
7356 }
7357 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007358
Douglas Gregor669a25a2011-02-17 00:22:45 +00007359 // Indexed and unordered accessors
7360 unsigned IndexedGetterPriority = CCP_CodePattern;
7361 unsigned IndexedSetterPriority = CCP_CodePattern;
7362 unsigned UnorderedGetterPriority = CCP_CodePattern;
7363 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007364 if (const auto *ObjCPointer =
7365 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007366 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7367 // If this interface type is not provably derived from a known
7368 // collection, penalize the corresponding completions.
7369 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007370 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007371 if (!InheritsFromClassNamed(IFace, "NSArray"))
7372 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7373 }
7374
7375 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007376 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007377 if (!InheritsFromClassNamed(IFace, "NSSet"))
7378 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7379 }
7380 }
7381 } else {
7382 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7383 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7384 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7385 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7386 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007387
Douglas Gregor669a25a2011-02-17 00:22:45 +00007388 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007389 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007390 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007391 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007392 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007393 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7394 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007395 if (ReturnType.isNull()) {
7396 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7397 Builder.AddTextChunk("NSUInteger");
7398 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7399 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007400
Fangrui Song050229d2018-11-24 00:14:31 +00007401 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7402 Results.AddResult(
7403 Result(Builder.TakeString(),
7404 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7405 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007406 }
7407 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007408
Douglas Gregor669a25a2011-02-17 00:22:45 +00007409 // Indexed getters
7410 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7411 if (IsInstanceMethod &&
7412 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007413 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007414 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007415 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007416 if (ReturnType.isNull()) {
7417 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7418 Builder.AddTextChunk("id");
7419 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007421
Douglas Gregor669a25a2011-02-17 00:22:45 +00007422 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7423 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7424 Builder.AddTextChunk("NSUInteger");
7425 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7426 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007427 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007428 CXCursor_ObjCInstanceMethodDecl));
7429 }
7430 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007431
Douglas Gregor669a25a2011-02-17 00:22:45 +00007432 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7433 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007434 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007435 (ReturnType->isObjCObjectPointerType() &&
7436 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007437 ReturnType->getAs<ObjCObjectPointerType>()
7438 ->getInterfaceDecl()
7439 ->getName() == "NSArray"))) {
7440 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007441 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007442 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007443 if (ReturnType.isNull()) {
7444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7445 Builder.AddTextChunk("NSArray *");
7446 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7447 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007448
Douglas Gregor669a25a2011-02-17 00:22:45 +00007449 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7450 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7451 Builder.AddTextChunk("NSIndexSet *");
7452 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7453 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007454 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007455 CXCursor_ObjCInstanceMethodDecl));
7456 }
7457 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007458
Douglas Gregor669a25a2011-02-17 00:22:45 +00007459 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7460 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007461 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007462 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7463 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007464
David Blaikie82e95a32014-11-19 07:49:47 +00007465 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007466 if (ReturnType.isNull()) {
7467 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7468 Builder.AddTextChunk("void");
7469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7470 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007471
Douglas Gregor669a25a2011-02-17 00:22:45 +00007472 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7473 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7474 Builder.AddPlaceholderChunk("object-type");
7475 Builder.AddTextChunk(" **");
7476 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7477 Builder.AddTextChunk("buffer");
7478 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7479 Builder.AddTypedTextChunk("range:");
7480 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7481 Builder.AddTextChunk("NSRange");
7482 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7483 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007484 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007485 CXCursor_ObjCInstanceMethodDecl));
7486 }
7487 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007488
Douglas Gregor669a25a2011-02-17 00:22:45 +00007489 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007490
Douglas Gregor669a25a2011-02-17 00:22:45 +00007491 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7492 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007493 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007494 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7495 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007496
David Blaikie82e95a32014-11-19 07:49:47 +00007497 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007498 if (ReturnType.isNull()) {
7499 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7500 Builder.AddTextChunk("void");
7501 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7502 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007503
Douglas Gregor669a25a2011-02-17 00:22:45 +00007504 Builder.AddTypedTextChunk("insertObject:");
7505 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7506 Builder.AddPlaceholderChunk("object-type");
7507 Builder.AddTextChunk(" *");
7508 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7509 Builder.AddTextChunk("object");
7510 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7511 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7512 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7513 Builder.AddPlaceholderChunk("NSUInteger");
7514 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7515 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007516 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007517 CXCursor_ObjCInstanceMethodDecl));
7518 }
7519 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007520
Douglas Gregor669a25a2011-02-17 00:22:45 +00007521 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7522 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007523 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007524 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7525 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007526
David Blaikie82e95a32014-11-19 07:49:47 +00007527 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007528 if (ReturnType.isNull()) {
7529 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7530 Builder.AddTextChunk("void");
7531 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7532 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007533
Douglas Gregor669a25a2011-02-17 00:22:45 +00007534 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7535 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7536 Builder.AddTextChunk("NSArray *");
7537 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7538 Builder.AddTextChunk("array");
7539 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7540 Builder.AddTypedTextChunk("atIndexes:");
7541 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7542 Builder.AddPlaceholderChunk("NSIndexSet *");
7543 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7544 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007545 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007546 CXCursor_ObjCInstanceMethodDecl));
7547 }
7548 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007549
Douglas Gregor669a25a2011-02-17 00:22:45 +00007550 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7551 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007552 std::string SelectorName =
7553 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007554 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007555 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007556 if (ReturnType.isNull()) {
7557 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7558 Builder.AddTextChunk("void");
7559 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7560 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007561
Douglas Gregor669a25a2011-02-17 00:22:45 +00007562 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7563 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7564 Builder.AddTextChunk("NSUInteger");
7565 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7566 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007567 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007568 CXCursor_ObjCInstanceMethodDecl));
7569 }
7570 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007571
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7573 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007574 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007575 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007576 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007577 if (ReturnType.isNull()) {
7578 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7579 Builder.AddTextChunk("void");
7580 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7581 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007582
Douglas Gregor669a25a2011-02-17 00:22:45 +00007583 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7584 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7585 Builder.AddTextChunk("NSIndexSet *");
7586 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7587 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007588 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007589 CXCursor_ObjCInstanceMethodDecl));
7590 }
7591 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007592
Douglas Gregor669a25a2011-02-17 00:22:45 +00007593 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7594 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007595 std::string SelectorName =
7596 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7597 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7598 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007599
David Blaikie82e95a32014-11-19 07:49:47 +00007600 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007601 if (ReturnType.isNull()) {
7602 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7603 Builder.AddTextChunk("void");
7604 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7605 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007606
Douglas Gregor669a25a2011-02-17 00:22:45 +00007607 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7608 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7609 Builder.AddPlaceholderChunk("NSUInteger");
7610 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7611 Builder.AddTextChunk("index");
7612 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7613 Builder.AddTypedTextChunk("withObject:");
7614 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7615 Builder.AddTextChunk("id");
7616 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7617 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007618 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007619 CXCursor_ObjCInstanceMethodDecl));
7620 }
7621 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007622
Douglas Gregor669a25a2011-02-17 00:22:45 +00007623 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7624 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007625 std::string SelectorName1 =
7626 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007627 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007628 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7629 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007630
David Blaikie82e95a32014-11-19 07:49:47 +00007631 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007632 if (ReturnType.isNull()) {
7633 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7634 Builder.AddTextChunk("void");
7635 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7636 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007637
Douglas Gregor669a25a2011-02-17 00:22:45 +00007638 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7639 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7640 Builder.AddPlaceholderChunk("NSIndexSet *");
7641 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7642 Builder.AddTextChunk("indexes");
7643 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7644 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7645 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7646 Builder.AddTextChunk("NSArray *");
7647 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7648 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007649 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007650 CXCursor_ObjCInstanceMethodDecl));
7651 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007652 }
7653
Douglas Gregor669a25a2011-02-17 00:22:45 +00007654 // Unordered getters
7655 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007656 if (IsInstanceMethod &&
7657 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007658 (ReturnType->isObjCObjectPointerType() &&
7659 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007660 ReturnType->getAs<ObjCObjectPointerType>()
7661 ->getInterfaceDecl()
7662 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007663 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007664 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007665 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7666 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007667 if (ReturnType.isNull()) {
7668 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7669 Builder.AddTextChunk("NSEnumerator *");
7670 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7671 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007672
Douglas Gregor669a25a2011-02-17 00:22:45 +00007673 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007674 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007675 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007676 }
7677 }
7678
7679 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007680 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007681 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007682 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007683 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007684 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007685 if (ReturnType.isNull()) {
7686 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7687 Builder.AddPlaceholderChunk("object-type");
7688 Builder.AddTextChunk(" *");
7689 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7690 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007691
Douglas Gregor669a25a2011-02-17 00:22:45 +00007692 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7693 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7694 if (ReturnType.isNull()) {
7695 Builder.AddPlaceholderChunk("object-type");
7696 Builder.AddTextChunk(" *");
7697 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007698 Builder.AddTextChunk(GetCompletionTypeString(
7699 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007700 }
7701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7702 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007703 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007704 CXCursor_ObjCInstanceMethodDecl));
7705 }
7706 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007707
Douglas Gregor669a25a2011-02-17 00:22:45 +00007708 // Mutable unordered accessors
7709 // - (void)addKeyObject:(type *)object
7710 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007711 std::string SelectorName =
7712 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007713 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007714 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007715 if (ReturnType.isNull()) {
7716 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7717 Builder.AddTextChunk("void");
7718 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7719 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007720
Douglas Gregor669a25a2011-02-17 00:22:45 +00007721 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7722 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7723 Builder.AddPlaceholderChunk("object-type");
7724 Builder.AddTextChunk(" *");
7725 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7726 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007727 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007728 CXCursor_ObjCInstanceMethodDecl));
7729 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007730 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007731
7732 // - (void)addKey:(NSSet *)objects
7733 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007734 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007735 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007736 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007737 if (ReturnType.isNull()) {
7738 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7739 Builder.AddTextChunk("void");
7740 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7741 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007742
Douglas Gregor669a25a2011-02-17 00:22:45 +00007743 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7744 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7745 Builder.AddTextChunk("NSSet *");
7746 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7747 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007748 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007749 CXCursor_ObjCInstanceMethodDecl));
7750 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007751 }
7752
Douglas Gregor669a25a2011-02-17 00:22:45 +00007753 // - (void)removeKeyObject:(type *)object
7754 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007755 std::string SelectorName =
7756 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007757 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007758 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007759 if (ReturnType.isNull()) {
7760 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7761 Builder.AddTextChunk("void");
7762 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7763 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007764
Douglas Gregor669a25a2011-02-17 00:22:45 +00007765 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7766 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7767 Builder.AddPlaceholderChunk("object-type");
7768 Builder.AddTextChunk(" *");
7769 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7770 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007771 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007772 CXCursor_ObjCInstanceMethodDecl));
7773 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007774 }
7775
Douglas Gregor669a25a2011-02-17 00:22:45 +00007776 // - (void)removeKey:(NSSet *)objects
7777 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007778 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007779 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007780 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007781 if (ReturnType.isNull()) {
7782 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7783 Builder.AddTextChunk("void");
7784 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7785 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007786
Douglas Gregor669a25a2011-02-17 00:22:45 +00007787 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7788 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7789 Builder.AddTextChunk("NSSet *");
7790 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7791 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007792 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007793 CXCursor_ObjCInstanceMethodDecl));
7794 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007795 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007796
7797 // - (void)intersectKey:(NSSet *)objects
7798 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007799 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007800 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007801 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007802 if (ReturnType.isNull()) {
7803 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7804 Builder.AddTextChunk("void");
7805 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7806 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007807
Douglas Gregor669a25a2011-02-17 00:22:45 +00007808 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7809 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7810 Builder.AddTextChunk("NSSet *");
7811 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7812 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007813 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007814 CXCursor_ObjCInstanceMethodDecl));
7815 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007816 }
7817
Douglas Gregor669a25a2011-02-17 00:22:45 +00007818 // Key-Value Observing
7819 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007820 if (!IsInstanceMethod &&
7821 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007822 (ReturnType->isObjCObjectPointerType() &&
7823 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007824 ReturnType->getAs<ObjCObjectPointerType>()
7825 ->getInterfaceDecl()
7826 ->getName() == "NSSet"))) {
7827 std::string SelectorName =
7828 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007829 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007830 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7831 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007832 if (ReturnType.isNull()) {
7833 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007834 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007835 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7836 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007837
Douglas Gregor669a25a2011-02-17 00:22:45 +00007838 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007839 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007840 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00007841 }
7842 }
7843
7844 // + (BOOL)automaticallyNotifiesObserversForKey
7845 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00007846 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007847 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007848 std::string SelectorName =
7849 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007850 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007851 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7852 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007853 if (ReturnType.isNull()) {
7854 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7855 Builder.AddTextChunk("BOOL");
7856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7857 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007858
Douglas Gregor857bcda2011-06-02 04:02:27 +00007859 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007860 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007861 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007862 }
7863 }
7864}
7865
Alex Lorenzb8740422017-10-24 16:39:37 +00007866void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007867 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007868 // Determine the return type of the method we're declaring, if
7869 // provided.
7870 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007871 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007872 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007873 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7874 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007875 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007876 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007877 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007878 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007879 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007880 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7881 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007882 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00007883 } else if (ObjCCategoryImplDecl *CatImpl =
7884 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007885 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007886 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007887 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007888 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007889 }
7890
7891 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007892 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007893 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007894 }
7895
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007896 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007897 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00007898 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007899 return;
7900 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007901
Douglas Gregor636a61e2010-04-07 00:21:17 +00007902 // Find all of the methods that we could declare/implement here.
7903 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00007904 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
7905 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007906
Douglas Gregor636a61e2010-04-07 00:21:17 +00007907 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007908 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007909 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007910 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007911 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007912 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007913 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007914 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007915 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007916 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007917 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007918 CodeCompletionBuilder Builder(Results.getAllocator(),
7919 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007920
7921 // Add the '-'/'+' prefix if it wasn't provided yet.
7922 if (!IsInstanceMethod) {
7923 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7924 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7925 }
7926
Douglas Gregor636a61e2010-04-07 00:21:17 +00007927 // If the result type was not already provided, add it to the
7928 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007929 if (ReturnType.isNull()) {
7930 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7931 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00007932 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
7933 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007934 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007935
7936 Selector Sel = Method->getSelector();
7937
7938 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00007939 Builder.AddTypedTextChunk(
7940 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007941
7942 // Add parameters to the pattern.
7943 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007944 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007945 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007946 P != PEnd; (void)++P, ++I) {
7947 // Add the part of the selector name.
7948 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007949 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007950 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007951 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7952 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00007953 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007954 } else
7955 break;
7956
7957 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007958 QualType ParamType;
7959 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7960 ParamType = (*P)->getType();
7961 else
7962 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00007963 ParamType = ParamType.substObjCTypeArgs(
7964 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007965 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00007966 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
7967 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007968
Douglas Gregor636a61e2010-04-07 00:21:17 +00007969 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00007970 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007971 }
7972
7973 if (Method->isVariadic()) {
7974 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007975 Builder.AddChunk(CodeCompletionString::CK_Comma);
7976 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007977 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007978
Douglas Gregord37c59d2010-05-28 00:57:46 +00007979 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007980 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007981 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7982 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7983 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007984 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007985 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007986 Builder.AddTextChunk("return");
7987 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7988 Builder.AddPlaceholderChunk("expression");
7989 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007990 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007991 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007992
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007993 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7994 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007995 }
7996
Douglas Gregor416b5752010-08-25 01:08:01 +00007997 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00007998 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007999 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008000 setInBaseClass(R);
8001 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008002 }
8003
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008004 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008005 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008006 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008007 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008008 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008009
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008010 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008011 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008012 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008013 M != MEnd; ++M)
8014 KnownSelectors.insert(M->first);
8015
Douglas Gregor669a25a2011-02-17 00:22:45 +00008016 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8017 if (!IFace)
8018 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8019 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008020
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008021 if (IFace)
8022 for (auto *Cat : IFace->visible_categories())
8023 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008024
8025 if (IsInstanceMethod) {
8026 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8027 for (auto *P : Containers[I]->instance_properties())
8028 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8029 KnownSelectors, Results);
8030 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008031 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008032
Douglas Gregor636a61e2010-04-07 00:21:17 +00008033 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008034
8035 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8036 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008037}
Douglas Gregor95887f92010-07-08 23:20:03 +00008038
Fangrui Song050229d2018-11-24 00:14:31 +00008039void Sema::CodeCompleteObjCMethodDeclSelector(
8040 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8041 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008042 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008043 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008044 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008045 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8046 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008047 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008048 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008049 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008050
8051 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008052 }
8053 }
8054
8055 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008056 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008057 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008058 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008059 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008060
Douglas Gregor95887f92010-07-08 23:20:03 +00008061 if (ReturnTy)
8062 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008063
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008064 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008065 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8066 MEnd = MethodPool.end();
8067 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008068 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8069 : &M->second.second;
8070 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008071 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008072 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008073
Douglas Gregor45879692010-07-08 23:37:41 +00008074 if (AtParameterName) {
8075 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008076 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008077 if (NumSelIdents &&
8078 NumSelIdents <= MethList->getMethod()->param_size()) {
8079 ParmVarDecl *Param =
8080 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008081 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008082 CodeCompletionBuilder Builder(Results.getAllocator(),
8083 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008084 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008085 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008086 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008087 }
8088 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008089
Douglas Gregor45879692010-07-08 23:37:41 +00008090 continue;
8091 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008092
Nico Weber2e0c8f72014-12-27 03:58:08 +00008093 Result R(MethList->getMethod(),
8094 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008095 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008096 R.AllParametersAreInformative = false;
8097 R.DeclaringEntity = true;
8098 Results.MaybeAddResult(R, CurContext);
8099 }
8100 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008101
Douglas Gregor95887f92010-07-08 23:20:03 +00008102 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008103
8104 if (!AtParameterName && !SelIdents.empty() &&
8105 SelIdents.front()->getName().startswith("init")) {
8106 for (const auto &M : PP.macros()) {
8107 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8108 continue;
8109 Results.EnterNewScope();
8110 CodeCompletionBuilder Builder(Results.getAllocator(),
8111 Results.getCodeCompletionTUInfo());
8112 Builder.AddTypedTextChunk(
8113 Builder.getAllocator().CopyString(M.first->getName()));
8114 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8115 CXCursor_MacroDefinition));
8116 Results.ExitScope();
8117 }
8118 }
8119
Eric Liuf5ba09f2018-07-04 10:01:18 +00008120 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8121 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008122}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008123
Douglas Gregorec00a262010-08-24 22:20:20 +00008124void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008125 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008126 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008127 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008128 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008129
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008130 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008131 CodeCompletionBuilder Builder(Results.getAllocator(),
8132 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008133 Builder.AddTypedTextChunk("if");
8134 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8135 Builder.AddPlaceholderChunk("condition");
8136 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008137
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008138 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008139 Builder.AddTypedTextChunk("ifdef");
8140 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8141 Builder.AddPlaceholderChunk("macro");
8142 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008143
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008144 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008145 Builder.AddTypedTextChunk("ifndef");
8146 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8147 Builder.AddPlaceholderChunk("macro");
8148 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008149
8150 if (InConditional) {
8151 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008152 Builder.AddTypedTextChunk("elif");
8153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8154 Builder.AddPlaceholderChunk("condition");
8155 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008156
8157 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008158 Builder.AddTypedTextChunk("else");
8159 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008160
8161 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008162 Builder.AddTypedTextChunk("endif");
8163 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008164 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008165
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008166 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008167 Builder.AddTypedTextChunk("include");
8168 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8169 Builder.AddTextChunk("\"");
8170 Builder.AddPlaceholderChunk("header");
8171 Builder.AddTextChunk("\"");
8172 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008173
8174 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008175 Builder.AddTypedTextChunk("include");
8176 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8177 Builder.AddTextChunk("<");
8178 Builder.AddPlaceholderChunk("header");
8179 Builder.AddTextChunk(">");
8180 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008181
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008182 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008183 Builder.AddTypedTextChunk("define");
8184 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8185 Builder.AddPlaceholderChunk("macro");
8186 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008187
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008188 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008189 Builder.AddTypedTextChunk("define");
8190 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8191 Builder.AddPlaceholderChunk("macro");
8192 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8193 Builder.AddPlaceholderChunk("args");
8194 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8195 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008196
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008197 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008198 Builder.AddTypedTextChunk("undef");
8199 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8200 Builder.AddPlaceholderChunk("macro");
8201 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008202
8203 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008204 Builder.AddTypedTextChunk("line");
8205 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8206 Builder.AddPlaceholderChunk("number");
8207 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008208
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008209 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008210 Builder.AddTypedTextChunk("line");
8211 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8212 Builder.AddPlaceholderChunk("number");
8213 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8214 Builder.AddTextChunk("\"");
8215 Builder.AddPlaceholderChunk("filename");
8216 Builder.AddTextChunk("\"");
8217 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008218
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008219 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008220 Builder.AddTypedTextChunk("error");
8221 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8222 Builder.AddPlaceholderChunk("message");
8223 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008224
8225 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008226 Builder.AddTypedTextChunk("pragma");
8227 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8228 Builder.AddPlaceholderChunk("arguments");
8229 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008230
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008231 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008232 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008233 Builder.AddTypedTextChunk("import");
8234 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8235 Builder.AddTextChunk("\"");
8236 Builder.AddPlaceholderChunk("header");
8237 Builder.AddTextChunk("\"");
8238 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008239
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008240 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008241 Builder.AddTypedTextChunk("import");
8242 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8243 Builder.AddTextChunk("<");
8244 Builder.AddPlaceholderChunk("header");
8245 Builder.AddTextChunk(">");
8246 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008247 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008248
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008249 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008250 Builder.AddTypedTextChunk("include_next");
8251 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8252 Builder.AddTextChunk("\"");
8253 Builder.AddPlaceholderChunk("header");
8254 Builder.AddTextChunk("\"");
8255 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008256
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008257 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008258 Builder.AddTypedTextChunk("include_next");
8259 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8260 Builder.AddTextChunk("<");
8261 Builder.AddPlaceholderChunk("header");
8262 Builder.AddTextChunk(">");
8263 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008264
8265 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008266 Builder.AddTypedTextChunk("warning");
8267 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8268 Builder.AddPlaceholderChunk("message");
8269 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008270
8271 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8272 // completions for them. And __include_macros is a Clang-internal extension
8273 // that we don't want to encourage anyone to use.
8274
8275 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8276 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008277
8278 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008279 Results.data(), Results.size());
8280}
8281
8282void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008283 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8284 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008285}
8286
Douglas Gregorec00a262010-08-24 22:20:20 +00008287void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008288 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008289 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008290 IsDefinition ? CodeCompletionContext::CCC_MacroName
8291 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008292 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008293 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008294 CodeCompletionBuilder Builder(Results.getAllocator(),
8295 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008296 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008297 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008298 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008299 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008300 Builder.AddTypedTextChunk(
8301 Builder.getAllocator().CopyString(M->first->getName()));
8302 Results.AddResult(CodeCompletionResult(
8303 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008304 }
8305 Results.ExitScope();
8306 } else if (IsDefinition) {
8307 // FIXME: Can we detect when the user just wrote an include guard above?
8308 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008309
Douglas Gregor0ac41382010-09-23 23:01:17 +00008310 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008311 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008312}
8313
Douglas Gregorec00a262010-08-24 22:20:20 +00008314void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008315 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008316 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008317 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008318
Douglas Gregorec00a262010-08-24 22:20:20 +00008319 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008320 AddMacroResults(PP, Results,
8321 CodeCompleter ? CodeCompleter->loadExternal() : false,
8322 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008323
Fangrui Song050229d2018-11-24 00:14:31 +00008324 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008325 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008326 CodeCompletionBuilder Builder(Results.getAllocator(),
8327 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008328 Builder.AddTypedTextChunk("defined");
8329 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8330 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8331 Builder.AddPlaceholderChunk("macro");
8332 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8333 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008334 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008335
8336 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8337 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008338}
8339
8340void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8341 IdentifierInfo *Macro,
8342 MacroInfo *MacroInfo,
8343 unsigned Argument) {
8344 // FIXME: In the future, we could provide "overload" results, much like we
8345 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008346
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008347 // Now just ignore this. There will be another code-completion callback
8348 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008349}
8350
Sam McCall3d8051a2018-09-18 08:40:41 +00008351// This handles completion inside an #include filename, e.g. #include <foo/ba
8352// We look for the directory "foo" under each directory on the include path,
8353// list its files, and reassemble the appropriate #include.
8354void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8355 // RelDir should use /, but unescaped \ is possible on windows!
8356 // Our completions will normalize to / for simplicity, this case is rare.
8357 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8358 // We need the native slashes for the actual file system interactions.
8359 SmallString<128> NativeRelDir = StringRef(RelDir);
8360 llvm::sys::path::native(NativeRelDir);
8361 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8362
8363 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8364 CodeCompleter->getCodeCompletionTUInfo(),
8365 CodeCompletionContext::CCC_IncludedFile);
8366 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8367
8368 // Helper: adds one file or directory completion result.
8369 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8370 SmallString<64> TypedChunk = Filename;
8371 // Directory completion is up to the slash, e.g. <sys/
8372 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8373 auto R = SeenResults.insert(TypedChunk);
8374 if (R.second) { // New completion
8375 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8376 *R.first = InternedTyped; // Avoid dangling StringRef.
8377 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8378 CodeCompleter->getCodeCompletionTUInfo());
8379 Builder.AddTypedTextChunk(InternedTyped);
8380 // The result is a "Pattern", which is pretty opaque.
8381 // We may want to include the real filename to allow smart ranking.
8382 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8383 }
8384 };
8385
8386 // Helper: scans IncludeDir for nice files, and adds results for each.
8387 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
8388 llvm::SmallString<128> Dir = IncludeDir;
8389 if (!NativeRelDir.empty())
8390 llvm::sys::path::append(Dir, NativeRelDir);
8391
8392 std::error_code EC;
8393 unsigned Count = 0;
8394 for (auto It = FS->dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008395 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008396 if (++Count == 2500) // If we happen to hit a huge directory,
8397 break; // bail out early so we're not too slow.
8398 StringRef Filename = llvm::sys::path::filename(It->path());
8399 switch (It->type()) {
8400 case llvm::sys::fs::file_type::directory_file:
8401 AddCompletion(Filename, /*IsDirectory=*/true);
8402 break;
8403 case llvm::sys::fs::file_type::regular_file:
8404 // Only files that really look like headers. (Except in system dirs).
8405 if (!IsSystem) {
8406 // Header extensions from Types.def, which we can't depend on here.
8407 if (!(Filename.endswith_lower(".h") ||
8408 Filename.endswith_lower(".hh") ||
8409 Filename.endswith_lower(".hpp") ||
8410 Filename.endswith_lower(".inc")))
8411 break;
8412 }
8413 AddCompletion(Filename, /*IsDirectory=*/false);
8414 break;
8415 default:
8416 break;
8417 }
8418 }
8419 };
8420
8421 // Helper: adds results relative to IncludeDir, if possible.
8422 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8423 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008424 switch (IncludeDir.getLookupType()) {
8425 case DirectoryLookup::LT_HeaderMap:
8426 // header maps are not (currently) enumerable.
8427 break;
8428 case DirectoryLookup::LT_NormalDir:
8429 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
8430 break;
8431 case DirectoryLookup::LT_Framework:
8432 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
8433 break;
8434 }
8435 };
8436
8437 // Finally with all our helpers, we can scan the include path.
8438 // Do this in standard order so deduplication keeps the right file.
8439 // (In case we decide to add more details to the results later).
8440 const auto &S = PP.getHeaderSearchInfo();
8441 using llvm::make_range;
8442 if (!Angled) {
8443 // The current directory is on the include path for "quoted" includes.
8444 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8445 if (CurFile && CurFile->getDir())
8446 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
8447 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8448 AddFilesFromDirLookup(D, false);
8449 }
8450 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008451 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008452 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8453 AddFilesFromDirLookup(D, true);
8454
8455 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8456 Results.data(), Results.size());
8457}
8458
Douglas Gregor11583702010-08-25 17:04:25 +00008459void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008460 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008461 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8462 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008463}
8464
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008465void Sema::CodeCompleteAvailabilityPlatformName() {
8466 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8467 CodeCompleter->getCodeCompletionTUInfo(),
8468 CodeCompletionContext::CCC_Other);
8469 Results.EnterNewScope();
8470 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8471 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8472 Results.AddResult(CodeCompletionResult(Platform));
8473 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8474 Twine(Platform) + "ApplicationExtension")));
8475 }
8476 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008477 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8478 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008479}
8480
Fangrui Song050229d2018-11-24 00:14:31 +00008481void Sema::GatherGlobalCodeCompletions(
8482 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8483 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008484 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8485 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008486 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008487 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008488 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008489 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8490 Consumer,
8491 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008492 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008493
Douglas Gregorb14904c2010-08-13 22:48:40 +00008494 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008495 AddMacroResults(PP, Builder,
8496 CodeCompleter ? CodeCompleter->loadExternal() : false,
8497 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008498
Douglas Gregorb14904c2010-08-13 22:48:40 +00008499 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008500 Results.insert(Results.end(), Builder.data(),
8501 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008502}