blob: 16e7308681439bc94e02631a34bdf2c5d47e36bd [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>
Ilya Biryukovcabab292019-05-24 10:18:39 +000040#include <string>
Douglas Gregor3545ff42009-09-21 16:56:56 +000041#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000042
43using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000044using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000045
Douglas Gregor3545ff42009-09-21 16:56:56 +000046namespace {
Fangrui Song050229d2018-11-24 00:14:31 +000047/// A container of code-completion results.
48class ResultBuilder {
49public:
50 /// The type of a name-lookup filter, which can be provided to the
51 /// name-lookup routines to specify which declarations should be included in
52 /// the result set (when it returns true) and which declarations should be
53 /// filtered out (returns false).
54 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000055
Fangrui Song050229d2018-11-24 00:14:31 +000056 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000057
Fangrui Song050229d2018-11-24 00:14:31 +000058private:
59 /// The actual results we have found.
60 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000061
Fangrui Song050229d2018-11-24 00:14:31 +000062 /// A record of all of the declarations we have found and placed
63 /// into the result set, used to ensure that no declaration ever gets into
64 /// the result set twice.
65 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000066
Fangrui Song050229d2018-11-24 00:14:31 +000067 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000068
Fangrui Song050229d2018-11-24 00:14:31 +000069 /// An entry in the shadow map, which is optimized to store
70 /// a single (declaration, index) mapping (the common case) but
71 /// can also store a list of (declaration, index) mappings.
72 class ShadowMapEntry {
73 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000074
Fangrui Song050229d2018-11-24 00:14:31 +000075 /// Contains either the solitary NamedDecl * or a vector
76 /// of (declaration, index) pairs.
77 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000078
Fangrui Song050229d2018-11-24 00:14:31 +000079 /// When the entry contains a single declaration, this is
80 /// the index associated with that entry.
81 unsigned SingleDeclIndex;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000082
Douglas Gregor3545ff42009-09-21 16:56:56 +000083 public:
Fangrui Song050229d2018-11-24 00:14:31 +000084 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000085
Fangrui Song050229d2018-11-24 00:14:31 +000086 void Add(const NamedDecl *ND, unsigned Index) {
87 if (DeclOrVector.isNull()) {
88 // 0 - > 1 elements: just set the single element information.
89 DeclOrVector = ND;
90 SingleDeclIndex = Index;
91 return;
92 }
93
94 if (const NamedDecl *PrevND =
95 DeclOrVector.dyn_cast<const NamedDecl *>()) {
96 // 1 -> 2 elements: create the vector of results and push in the
97 // existing declaration.
98 DeclIndexPairVector *Vec = new DeclIndexPairVector;
99 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
100 DeclOrVector = Vec;
101 }
102
103 // Add the new element to the end of the vector.
104 DeclOrVector.get<DeclIndexPairVector *>()->push_back(
105 DeclIndexPair(ND, Index));
106 }
107
108 void Destroy() {
109 if (DeclIndexPairVector *Vec =
110 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
111 delete Vec;
112 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05fcf842010-11-02 20:36:02 +0000113 }
114 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000115
Fangrui Song050229d2018-11-24 00:14:31 +0000116 // Iteration.
117 class iterator;
118 iterator begin() const;
119 iterator end() const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000120 };
Fangrui Song050229d2018-11-24 00:14:31 +0000121
122 /// A mapping from declaration names to the declarations that have
123 /// this name within a particular scope and their index within the list of
124 /// results.
125 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
126
127 /// The semantic analysis object for which results are being
128 /// produced.
129 Sema &SemaRef;
130
131 /// The allocator used to allocate new code-completion strings.
132 CodeCompletionAllocator &Allocator;
133
134 CodeCompletionTUInfo &CCTUInfo;
135
136 /// If non-NULL, a filter function used to remove any code-completion
137 /// results that are not desirable.
138 LookupFilter Filter;
139
140 /// Whether we should allow declarations as
141 /// nested-name-specifiers that would otherwise be filtered out.
142 bool AllowNestedNameSpecifiers;
143
144 /// If set, the type that we would prefer our resulting value
145 /// declarations to have.
146 ///
147 /// Closely matching the preferred type gives a boost to a result's
148 /// priority.
149 CanQualType PreferredType;
150
151 /// A list of shadow maps, which is used to model name hiding at
152 /// different levels of, e.g., the inheritance hierarchy.
153 std::list<ShadowMap> ShadowMaps;
154
155 /// If we're potentially referring to a C++ member function, the set
156 /// of qualifiers applied to the object type.
157 Qualifiers ObjectTypeQualifiers;
158
159 /// Whether the \p ObjectTypeQualifiers field is active.
160 bool HasObjectTypeQualifiers;
161
162 /// The selector that we prefer.
163 Selector PreferredSelector;
164
165 /// The completion context in which we are gathering results.
166 CodeCompletionContext CompletionContext;
167
168 /// If we are in an instance method definition, the \@implementation
169 /// object.
170 ObjCImplementationDecl *ObjCImplementation;
171
172 void AdjustResultPriorityForDecl(Result &R);
173
174 void MaybeAddConstructorResults(Result R);
175
176public:
177 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
178 CodeCompletionTUInfo &CCTUInfo,
179 const CodeCompletionContext &CompletionContext,
180 LookupFilter Filter = nullptr)
181 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
182 Filter(Filter), AllowNestedNameSpecifiers(false),
183 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
184 ObjCImplementation(nullptr) {
185 // If this is an Objective-C instance method definition, dig out the
186 // corresponding implementation.
187 switch (CompletionContext.getKind()) {
188 case CodeCompletionContext::CCC_Expression:
189 case CodeCompletionContext::CCC_ObjCMessageReceiver:
190 case CodeCompletionContext::CCC_ParenthesizedExpression:
191 case CodeCompletionContext::CCC_Statement:
192 case CodeCompletionContext::CCC_Recovery:
193 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
194 if (Method->isInstanceMethod())
195 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
196 ObjCImplementation = Interface->getImplementation();
197 break;
198
199 default:
200 break;
201 }
202 }
203
204 /// Determine the priority for a reference to the given declaration.
205 unsigned getBasePriority(const NamedDecl *D);
206
207 /// Whether we should include code patterns in the completion
208 /// results.
209 bool includeCodePatterns() const {
210 return SemaRef.CodeCompleter &&
211 SemaRef.CodeCompleter->includeCodePatterns();
212 }
213
214 /// Set the filter used for code-completion results.
215 void setFilter(LookupFilter Filter) { this->Filter = Filter; }
216
217 Result *data() { return Results.empty() ? nullptr : &Results.front(); }
218 unsigned size() const { return Results.size(); }
219 bool empty() const { return Results.empty(); }
220
221 /// Specify the preferred type.
222 void setPreferredType(QualType T) {
223 PreferredType = SemaRef.Context.getCanonicalType(T);
224 }
225
226 /// Set the cv-qualifiers on the object type, for us in filtering
227 /// calls to member functions.
228 ///
229 /// When there are qualifiers in this set, they will be used to filter
230 /// out member functions that aren't available (because there will be a
231 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
232 /// match.
233 void setObjectTypeQualifiers(Qualifiers Quals) {
234 ObjectTypeQualifiers = Quals;
235 HasObjectTypeQualifiers = true;
236 }
237
238 /// Set the preferred selector.
239 ///
240 /// When an Objective-C method declaration result is added, and that
241 /// method's selector matches this preferred selector, we give that method
242 /// a slight priority boost.
243 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
244
245 /// Retrieve the code-completion context for which results are
246 /// being collected.
247 const CodeCompletionContext &getCompletionContext() const {
248 return CompletionContext;
249 }
250
251 /// Specify whether nested-name-specifiers are allowed.
252 void allowNestedNameSpecifiers(bool Allow = true) {
253 AllowNestedNameSpecifiers = Allow;
254 }
255
256 /// Return the semantic analysis object for which we are collecting
257 /// code completion results.
258 Sema &getSema() const { return SemaRef; }
259
260 /// Retrieve the allocator used to allocate code completion strings.
261 CodeCompletionAllocator &getAllocator() const { return Allocator; }
262
263 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
264
265 /// Determine whether the given declaration is at all interesting
266 /// as a code-completion result.
267 ///
268 /// \param ND the declaration that we are inspecting.
269 ///
270 /// \param AsNestedNameSpecifier will be set true if this declaration is
271 /// only interesting when it is a nested-name-specifier.
272 bool isInterestingDecl(const NamedDecl *ND,
273 bool &AsNestedNameSpecifier) const;
274
275 /// Check whether the result is hidden by the Hiding declaration.
276 ///
277 /// \returns true if the result is hidden and cannot be found, false if
278 /// the hidden result could still be found. When false, \p R may be
279 /// modified to describe how the result can be found (e.g., via extra
280 /// qualification).
281 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
282 const NamedDecl *Hiding);
283
284 /// Add a new result to this result set (if it isn't already in one
285 /// of the shadow maps), or replace an existing result (for, e.g., a
286 /// redeclaration).
287 ///
288 /// \param R the result to add (if it is unique).
289 ///
290 /// \param CurContext the context in which this result will be named.
291 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
292
293 /// Add a new result to this result set, where we already know
294 /// the hiding declaration (if any).
295 ///
296 /// \param R the result to add (if it is unique).
297 ///
298 /// \param CurContext the context in which this result will be named.
299 ///
300 /// \param Hiding the declaration that hides the result.
301 ///
302 /// \param InBaseClass whether the result was found in a base
303 /// class of the searched context.
304 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
305 bool InBaseClass);
306
307 /// Add a new non-declaration result to this result set.
308 void AddResult(Result R);
309
310 /// Enter into a new scope.
311 void EnterNewScope();
312
313 /// Exit from the current scope.
314 void ExitScope();
315
316 /// Ignore this declaration, if it is seen again.
317 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
318
319 /// Add a visited context.
320 void addVisitedContext(DeclContext *Ctx) {
321 CompletionContext.addVisitedContext(Ctx);
322 }
323
324 /// \name Name lookup predicates
325 ///
326 /// These predicates can be passed to the name lookup functions to filter the
327 /// results of name lookup. All of the predicates have the same type, so that
328 ///
329 //@{
330 bool IsOrdinaryName(const NamedDecl *ND) const;
331 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
332 bool IsIntegralConstantValue(const NamedDecl *ND) const;
333 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
334 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
335 bool IsEnum(const NamedDecl *ND) const;
336 bool IsClassOrStruct(const NamedDecl *ND) const;
337 bool IsUnion(const NamedDecl *ND) const;
338 bool IsNamespace(const NamedDecl *ND) const;
339 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
340 bool IsType(const NamedDecl *ND) const;
341 bool IsMember(const NamedDecl *ND) const;
342 bool IsObjCIvar(const NamedDecl *ND) const;
343 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
344 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
345 bool IsObjCCollection(const NamedDecl *ND) const;
346 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
347 //@}
348};
349} // namespace
Douglas Gregor3545ff42009-09-21 16:56:56 +0000350
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000351void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
352 if (isa<BlockDecl>(S.CurContext)) {
353 if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000354 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000355 Type = BSI->ReturnType;
356 ExpectedLoc = Tok;
357 }
358 } else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000359 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000360 Type = Function->getReturnType();
361 ExpectedLoc = Tok;
362 } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000363 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000364 Type = Method->getReturnType();
365 ExpectedLoc = Tok;
366 }
367}
368
369void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {
370 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000371 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000372 Type = VD ? VD->getType() : QualType();
373 ExpectedLoc = Tok;
374}
375
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000376void PreferredTypeBuilder::enterFunctionArgument(
377 SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) {
378 this->ComputeType = ComputeType;
379 Type = QualType();
380 ExpectedLoc = Tok;
381}
382
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000383void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,
384 SourceLocation LParLoc) {
385 // expected type for parenthesized expression does not change.
386 if (ExpectedLoc == LParLoc)
387 ExpectedLoc = Tok;
388}
389
390static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
391 tok::TokenKind Op) {
392 if (!LHS)
393 return QualType();
394
395 QualType LHSType = LHS->getType();
396 if (LHSType->isPointerType()) {
397 if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
398 return S.getASTContext().getPointerDiffType();
399 // Pointer difference is more common than subtracting an int from a pointer.
400 if (Op == tok::minus)
401 return LHSType;
402 }
403
404 switch (Op) {
405 // No way to infer the type of RHS from LHS.
406 case tok::comma:
407 return QualType();
408 // Prefer the type of the left operand for all of these.
409 // Arithmetic operations.
410 case tok::plus:
411 case tok::plusequal:
412 case tok::minus:
413 case tok::minusequal:
414 case tok::percent:
415 case tok::percentequal:
416 case tok::slash:
417 case tok::slashequal:
418 case tok::star:
419 case tok::starequal:
420 // Assignment.
421 case tok::equal:
422 // Comparison operators.
423 case tok::equalequal:
424 case tok::exclaimequal:
425 case tok::less:
426 case tok::lessequal:
427 case tok::greater:
428 case tok::greaterequal:
429 case tok::spaceship:
430 return LHS->getType();
431 // Binary shifts are often overloaded, so don't try to guess those.
432 case tok::greatergreater:
433 case tok::greatergreaterequal:
434 case tok::lessless:
435 case tok::lesslessequal:
436 if (LHSType->isIntegralOrEnumerationType())
437 return S.getASTContext().IntTy;
438 return QualType();
439 // Logical operators, assume we want bool.
440 case tok::ampamp:
441 case tok::pipepipe:
442 case tok::caretcaret:
443 return S.getASTContext().BoolTy;
444 // Operators often used for bit manipulation are typically used with the type
445 // of the left argument.
446 case tok::pipe:
447 case tok::pipeequal:
448 case tok::caret:
449 case tok::caretequal:
450 case tok::amp:
451 case tok::ampequal:
452 if (LHSType->isIntegralOrEnumerationType())
453 return LHSType;
454 return QualType();
455 // RHS should be a pointer to a member of the 'LHS' type, but we can't give
456 // any particular type here.
457 case tok::periodstar:
458 case tok::arrowstar:
459 return QualType();
460 default:
461 // FIXME(ibiryukov): handle the missing op, re-add the assertion.
462 // assert(false && "unhandled binary op");
463 return QualType();
464 }
465}
466
467/// Get preferred type for an argument of an unary expression. \p ContextType is
468/// preferred type of the whole unary expression.
469static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType,
470 tok::TokenKind Op) {
471 switch (Op) {
472 case tok::exclaim:
473 return S.getASTContext().BoolTy;
474 case tok::amp:
475 if (!ContextType.isNull() && ContextType->isPointerType())
476 return ContextType->getPointeeType();
477 return QualType();
478 case tok::star:
479 if (ContextType.isNull())
480 return QualType();
481 return S.getASTContext().getPointerType(ContextType.getNonReferenceType());
482 case tok::plus:
483 case tok::minus:
484 case tok::tilde:
485 case tok::minusminus:
486 case tok::plusplus:
487 if (ContextType.isNull())
488 return S.getASTContext().IntTy;
489 // leave as is, these operators typically return the same type.
490 return ContextType;
491 case tok::kw___real:
492 case tok::kw___imag:
493 return QualType();
494 default:
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000495 assert(false && "unhandled unary op");
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000496 return QualType();
497 }
498}
499
500void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,
501 tok::TokenKind Op) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000502 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000503 Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);
504 ExpectedLoc = Tok;
505}
506
507void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok,
508 Expr *Base) {
509 if (!Base)
510 return;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000511 // Do we have expected type for Base?
512 if (ExpectedLoc != Base->getBeginLoc())
513 return;
514 // Keep the expected type, only update the location.
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000515 ExpectedLoc = Tok;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000516 return;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000517}
518
519void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,
520 tok::TokenKind OpKind,
521 SourceLocation OpLoc) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000522 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000523 Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);
524 ExpectedLoc = Tok;
525}
526
527void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,
528 Expr *LHS) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000529 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000530 Type = S.getASTContext().IntTy;
531 ExpectedLoc = Tok;
532}
533
534void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,
535 QualType CastType) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000536 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000537 Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();
538 ExpectedLoc = Tok;
539}
540
541void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000542 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000543 Type = S.getASTContext().BoolTy;
544 ExpectedLoc = Tok;
545}
546
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000547class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000548 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000549 unsigned SingleDeclIndex;
550
551public:
552 typedef DeclIndexPair value_type;
553 typedef value_type reference;
554 typedef std::ptrdiff_t difference_type;
555 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000556
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000557 class pointer {
558 DeclIndexPair Value;
559
560 public:
Fangrui Song050229d2018-11-24 00:14:31 +0000561 pointer(const DeclIndexPair &Value) : Value(Value) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000562
Fangrui Song050229d2018-11-24 00:14:31 +0000563 const DeclIndexPair *operator->() const { return &Value; }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000564 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000565
566 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000567
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000568 iterator(const NamedDecl *SingleDecl, unsigned Index)
Fangrui Song050229d2018-11-24 00:14:31 +0000569 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000570
571 iterator(const DeclIndexPair *Iterator)
Fangrui Song050229d2018-11-24 00:14:31 +0000572 : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000573
574 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000575 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000576 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000577 SingleDeclIndex = 0;
578 return *this;
579 }
580
Fangrui Song050229d2018-11-24 00:14:31 +0000581 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000582 ++I;
583 DeclOrIterator = I;
584 return *this;
585 }
586
Chris Lattner9795b392010-09-04 18:12:20 +0000587 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000588 iterator tmp(*this);
589 ++(*this);
590 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000591 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000592
593 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000594 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000595 return reference(ND, SingleDeclIndex);
596
Fangrui Song050229d2018-11-24 00:14:31 +0000597 return *DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000598 }
599
Fangrui Song050229d2018-11-24 00:14:31 +0000600 pointer operator->() const { return pointer(**this); }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000601
602 friend bool operator==(const iterator &X, const iterator &Y) {
Fangrui Song050229d2018-11-24 00:14:31 +0000603 return X.DeclOrIterator.getOpaqueValue() ==
604 Y.DeclOrIterator.getOpaqueValue() &&
605 X.SingleDeclIndex == Y.SingleDeclIndex;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000606 }
607
608 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000609 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000610 }
611};
612
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000613ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000614ResultBuilder::ShadowMapEntry::begin() const {
615 if (DeclOrVector.isNull())
616 return iterator();
617
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000618 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000619 return iterator(ND, SingleDeclIndex);
620
621 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
622}
623
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000624ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000625ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000626 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000627 return iterator();
628
629 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
630}
631
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000632/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000633/// (\p CurContext) to the target context (\p TargetContext).
634///
635/// \param Context the AST context in which the qualification will be used.
636///
637/// \param CurContext the context where an entity is being named, which is
638/// typically based on the current scope.
639///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000640/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000641/// resides.
642///
643/// \returns a nested name specifier that refers into the target context, or
644/// NULL if no qualification is needed.
645static NestedNameSpecifier *
Fangrui Song050229d2018-11-24 00:14:31 +0000646getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000647 const DeclContext *TargetContext) {
648 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000649
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000650 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000651 CommonAncestor && !CommonAncestor->Encloses(CurContext);
652 CommonAncestor = CommonAncestor->getLookupParent()) {
653 if (CommonAncestor->isTransparentContext() ||
654 CommonAncestor->isFunctionOrMethod())
655 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000656
Douglas Gregor2af2f672009-09-21 20:12:40 +0000657 TargetParents.push_back(CommonAncestor);
658 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000659
660 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000661 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000662 const DeclContext *Parent = TargetParents.pop_back_val();
663
Fangrui Song050229d2018-11-24 00:14:31 +0000664 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000665 if (!Namespace->getIdentifier())
666 continue;
667
Douglas Gregor2af2f672009-09-21 20:12:40 +0000668 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Fangrui Song050229d2018-11-24 00:14:31 +0000669 } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
670 Result = NestedNameSpecifier::Create(
671 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000672 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000673 return Result;
674}
675
Alp Toker034bbd52014-06-30 01:33:53 +0000676/// Determine whether \p Id is a name reserved for the implementation (C99
677/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000678static bool isReservedName(const IdentifierInfo *Id,
679 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000680 if (Id->getLength() < 2)
681 return false;
682 const char *Name = Id->getNameStart();
683 return Name[0] == '_' &&
Fangrui Song050229d2018-11-24 00:14:31 +0000684 (Name[1] == '_' ||
685 (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000686}
687
688// Some declarations have reserved names that we don't want to ever show.
689// Filter out names reserved for the implementation if they come from a
690// system header.
691static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
692 const IdentifierInfo *Id = ND->getIdentifier();
693 if (!Id)
694 return false;
695
696 // Ignore reserved names for compiler provided decls.
697 if (isReservedName(Id) && ND->getLocation().isInvalid())
698 return true;
699
700 // For system headers ignore only double-underscore names.
701 // This allows for system headers providing private symbols with a single
702 // underscore.
703 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000704 SemaRef.SourceMgr.isInSystemHeader(
705 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
706 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000707
708 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000709}
710
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000711bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000712 bool &AsNestedNameSpecifier) const {
713 AsNestedNameSpecifier = false;
714
Richard Smithf2005d32015-12-29 23:34:32 +0000715 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000716 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000717
718 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000719 if (!ND->getDeclName())
720 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000721
Douglas Gregor3545ff42009-09-21 16:56:56 +0000722 // Friend declarations and declarations introduced due to friends are never
723 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000724 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000725 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000726
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000727 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000728 if (isa<ClassTemplateSpecializationDecl>(ND) ||
729 isa<ClassTemplatePartialSpecializationDecl>(ND))
730 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000731
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000732 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000733 if (isa<UsingDecl>(ND))
734 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000735
736 if (shouldIgnoreDueToReservedName(ND, SemaRef))
737 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000738
Douglas Gregor59cab552010-08-16 23:05:20 +0000739 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000740 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
741 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000742 AsNestedNameSpecifier = true;
743
Douglas Gregor3545ff42009-09-21 16:56:56 +0000744 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000745 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000746 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000747 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000748 IsNestedNameSpecifier(ND) &&
749 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000750 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000751 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
752 AsNestedNameSpecifier = true;
753 return true;
754 }
755
Douglas Gregor7c208612010-01-14 00:20:49 +0000756 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000757 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000758 // ... then it must be interesting!
759 return true;
760}
761
Douglas Gregore0717ab2010-01-14 00:41:07 +0000762bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000763 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000764 // In C, there is no way to refer to a hidden name.
765 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
766 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000767 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000768 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000769
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000770 const DeclContext *HiddenCtx =
771 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000772
Douglas Gregore0717ab2010-01-14 00:41:07 +0000773 // There is no way to qualify a name declared in a function or method.
774 if (HiddenCtx->isFunctionOrMethod())
775 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000776
Sebastian Redl50c68252010-08-31 00:36:30 +0000777 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000778 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000779
Douglas Gregore0717ab2010-01-14 00:41:07 +0000780 // We can refer to the result with the appropriate qualification. Do it.
781 R.Hidden = true;
782 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000783
Douglas Gregore0717ab2010-01-14 00:41:07 +0000784 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000785 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000786 R.Declaration->getDeclContext());
787 return false;
788}
789
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000790/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000791/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000792SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000793 switch (T->getTypeClass()) {
794 case Type::Builtin:
795 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000796 case BuiltinType::Void:
797 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000798
Fangrui Song050229d2018-11-24 00:14:31 +0000799 case BuiltinType::NullPtr:
800 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000801
Fangrui Song050229d2018-11-24 00:14:31 +0000802 case BuiltinType::Overload:
803 case BuiltinType::Dependent:
804 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000805
Fangrui Song050229d2018-11-24 00:14:31 +0000806 case BuiltinType::ObjCId:
807 case BuiltinType::ObjCClass:
808 case BuiltinType::ObjCSel:
809 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000810
Fangrui Song050229d2018-11-24 00:14:31 +0000811 default:
812 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000813 }
David Blaikie8a40f702012-01-17 06:56:22 +0000814
Douglas Gregor95887f92010-07-08 23:20:03 +0000815 case Type::Complex:
816 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000817
Douglas Gregor95887f92010-07-08 23:20:03 +0000818 case Type::Pointer:
819 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000820
Douglas Gregor95887f92010-07-08 23:20:03 +0000821 case Type::BlockPointer:
822 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000823
Douglas Gregor95887f92010-07-08 23:20:03 +0000824 case Type::LValueReference:
825 case Type::RValueReference:
826 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000827
Douglas Gregor95887f92010-07-08 23:20:03 +0000828 case Type::ConstantArray:
829 case Type::IncompleteArray:
830 case Type::VariableArray:
831 case Type::DependentSizedArray:
832 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000833
Douglas Gregor95887f92010-07-08 23:20:03 +0000834 case Type::DependentSizedExtVector:
835 case Type::Vector:
836 case Type::ExtVector:
837 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000838
Douglas Gregor95887f92010-07-08 23:20:03 +0000839 case Type::FunctionProto:
840 case Type::FunctionNoProto:
841 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000842
Douglas Gregor95887f92010-07-08 23:20:03 +0000843 case Type::Record:
844 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000845
Douglas Gregor95887f92010-07-08 23:20:03 +0000846 case Type::Enum:
847 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000848
Douglas Gregor95887f92010-07-08 23:20:03 +0000849 case Type::ObjCObject:
850 case Type::ObjCInterface:
851 case Type::ObjCObjectPointer:
852 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000853
Douglas Gregor95887f92010-07-08 23:20:03 +0000854 default:
855 return STC_Other;
856 }
857}
858
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000859/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000860/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000861QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000862 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000863
Fangrui Song050229d2018-11-24 00:14:31 +0000864 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000865 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000866 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000867 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000868
Douglas Gregor95887f92010-07-08 23:20:03 +0000869 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000870 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000871 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000872 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000873 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000874 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000875 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000876 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000877 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000878 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000879 T = Value->getType();
Ilya Biryukovc514ade2019-01-24 10:41:43 +0000880
881 if (T.isNull())
Douglas Gregor95887f92010-07-08 23:20:03 +0000882 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000883
884 // Dig through references, function pointers, and block pointers to
885 // get down to the likely type of an expression when the entity is
886 // used.
887 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000888 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000889 T = Ref->getPointeeType();
890 continue;
891 }
892
Fangrui Song050229d2018-11-24 00:14:31 +0000893 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000894 if (Pointer->getPointeeType()->isFunctionType()) {
895 T = Pointer->getPointeeType();
896 continue;
897 }
898
899 break;
900 }
901
Fangrui Song050229d2018-11-24 00:14:31 +0000902 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000903 T = Block->getPointeeType();
904 continue;
905 }
906
Fangrui Song050229d2018-11-24 00:14:31 +0000907 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000908 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000909 continue;
910 }
911
912 break;
913 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000914
Douglas Gregoraf670a82011-04-14 20:33:34 +0000915 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000916}
917
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000918unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
919 if (!ND)
920 return CCP_Unlikely;
921
922 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000923 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
924 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000925 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000926 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000927 if (ImplicitParam->getIdentifier() &&
928 ImplicitParam->getIdentifier()->isStr("_cmd"))
929 return CCP_ObjC_cmd;
930
931 return CCP_LocalDeclaration;
932 }
Richard Smith541b38b2013-09-20 01:15:31 +0000933
934 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000935 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
936 // Explicit destructor calls are very rare.
937 if (isa<CXXDestructorDecl>(ND))
938 return CCP_Unlikely;
939 // Explicit operator and conversion function calls are also very rare.
940 auto DeclNameKind = ND->getDeclName().getNameKind();
941 if (DeclNameKind == DeclarationName::CXXOperatorName ||
942 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
943 DeclNameKind == DeclarationName::CXXConversionFunctionName)
944 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000945 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000946 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000947
948 // Content-based decisions.
949 if (isa<EnumConstantDecl>(ND))
950 return CCP_Constant;
951
Douglas Gregor52e0de42013-01-31 05:03:46 +0000952 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
953 // message receiver, or parenthesized expression context. There, it's as
954 // likely that the user will want to write a type as other declarations.
955 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
956 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000957 CompletionContext.getKind() ==
958 CodeCompletionContext::CCC_ObjCMessageReceiver ||
959 CompletionContext.getKind() ==
960 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000961 return CCP_Type;
962
963 return CCP_Declaration;
964}
965
Douglas Gregor50832e02010-09-20 22:39:41 +0000966void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
967 // If this is an Objective-C method declaration whose selector matches our
968 // preferred selector, give it a priority boost.
969 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000970 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000971 if (PreferredSelector == Method->getSelector())
972 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000973
Douglas Gregor50832e02010-09-20 22:39:41 +0000974 // If we have a preferred type, adjust the priority for results with exactly-
975 // matching or nearly-matching types.
976 if (!PreferredType.isNull()) {
977 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
978 if (!T.isNull()) {
979 CanQualType TC = SemaRef.Context.getCanonicalType(T);
980 // Check for exactly-matching types (modulo qualifiers).
981 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
982 R.Priority /= CCF_ExactTypeMatch;
983 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +0000984 else if ((getSimplifiedTypeClass(PreferredType) ==
985 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000986 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000987 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000988 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000989 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000990}
991
Benjamin Kramer756ecb82019-02-11 14:52:15 +0000992static DeclContext::lookup_result getConstructors(ASTContext &Context,
993 const CXXRecordDecl *Record) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +0000994 QualType RecordTy = Context.getTypeDeclType(Record);
995 DeclarationName ConstructorName =
996 Context.DeclarationNames.getCXXConstructorName(
997 Context.getCanonicalType(RecordTy));
998 return Record->lookup(ConstructorName);
999}
1000
Douglas Gregor0212fd72010-09-21 16:06:22 +00001001void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001002 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +00001003 !CompletionContext.wantConstructorResults())
1004 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001005
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001006 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +00001007 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001008 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001009 Record = ClassTemplate->getTemplatedDecl();
1010 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
1011 // Skip specializations and partial specializations.
1012 if (isa<ClassTemplateSpecializationDecl>(Record))
1013 return;
1014 } else {
1015 // There are no constructors here.
1016 return;
1017 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001018
Douglas Gregor0212fd72010-09-21 16:06:22 +00001019 Record = Record->getDefinition();
1020 if (!Record)
1021 return;
1022
Fangrui Song050229d2018-11-24 00:14:31 +00001023 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001024 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001025 R.CursorKind = getCursorKindForDecl(R.Declaration);
1026 Results.push_back(R);
1027 }
1028}
1029
Sam McCall63c59722018-01-22 20:44:47 +00001030static bool isConstructor(const Decl *ND) {
1031 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
1032 ND = Tmpl->getTemplatedDecl();
1033 return isa<CXXConstructorDecl>(ND);
1034}
1035
Douglas Gregor7c208612010-01-14 00:20:49 +00001036void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
1037 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001038
Douglas Gregor7c208612010-01-14 00:20:49 +00001039 if (R.Kind != Result::RK_Declaration) {
1040 // For non-declaration results, just add the result.
1041 Results.push_back(R);
1042 return;
1043 }
1044
1045 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001046 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
1047 CodeCompletionResult Result(Using->getTargetDecl(),
1048 getBasePriority(Using->getTargetDecl()),
1049 R.Qualifier);
1050 Result.ShadowDecl = Using;
1051 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +00001052 return;
1053 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001054
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001055 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +00001056 unsigned IDNS = CanonDecl->getIdentifierNamespace();
1057
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001058 bool AsNestedNameSpecifier = false;
1059 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +00001060 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001061
Douglas Gregor0212fd72010-09-21 16:06:22 +00001062 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001063 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001064 return;
1065
Douglas Gregor3545ff42009-09-21 16:56:56 +00001066 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001067 ShadowMapEntry::iterator I, IEnd;
1068 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
1069 if (NamePos != SMap.end()) {
1070 I = NamePos->second.begin();
1071 IEnd = NamePos->second.end();
1072 }
1073
1074 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001075 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001076 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001077 if (ND->getCanonicalDecl() == CanonDecl) {
1078 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001079 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001080
Douglas Gregor3545ff42009-09-21 16:56:56 +00001081 // We're done.
1082 return;
1083 }
1084 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001085
Douglas Gregor3545ff42009-09-21 16:56:56 +00001086 // This is a new declaration in this scope. However, check whether this
1087 // declaration name is hidden by a similarly-named declaration in an outer
1088 // scope.
1089 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
1090 --SMEnd;
1091 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001092 ShadowMapEntry::iterator I, IEnd;
1093 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
1094 if (NamePos != SM->end()) {
1095 I = NamePos->second.begin();
1096 IEnd = NamePos->second.end();
1097 }
1098 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001099 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +00001100 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +00001101 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
1102 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001103 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001104
Douglas Gregor3545ff42009-09-21 16:56:56 +00001105 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +00001106 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
1107 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001108 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001109 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001110
Douglas Gregor3545ff42009-09-21 16:56:56 +00001111 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +00001112 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001113 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001114
Douglas Gregor3545ff42009-09-21 16:56:56 +00001115 break;
1116 }
1117 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001118
Douglas Gregor3545ff42009-09-21 16:56:56 +00001119 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001120 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001121 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00001122
Douglas Gregore412a5a2009-09-23 22:26:46 +00001123 // If the filter is for nested-name-specifiers, then this result starts a
1124 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001125 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +00001126 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001127 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001128 } else
Fangrui Song050229d2018-11-24 00:14:31 +00001129 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001130
Douglas Gregor5bf52692009-09-22 23:15:58 +00001131 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +00001132 if (R.QualifierIsInformative && !R.Qualifier &&
1133 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001134 const DeclContext *Ctx = R.Declaration->getDeclContext();
1135 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001136 R.Qualifier =
1137 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001138 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001139 R.Qualifier = NestedNameSpecifier::Create(
1140 SemaRef.Context, nullptr, false,
1141 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +00001142 else
1143 R.QualifierIsInformative = false;
1144 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001145
Douglas Gregor3545ff42009-09-21 16:56:56 +00001146 // Insert this result into the set of results and into the current shadow
1147 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001148 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001149 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001150
Douglas Gregor0212fd72010-09-21 16:06:22 +00001151 if (!AsNestedNameSpecifier)
1152 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001153}
1154
Eric Liu4a7cd632018-10-24 12:57:27 +00001155static void setInBaseClass(ResultBuilder::Result &R) {
1156 R.Priority += CCD_InBaseClass;
1157 R.InBaseClass = true;
1158}
1159
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001160void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +00001161 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001162 if (R.Kind != Result::RK_Declaration) {
1163 // For non-declaration results, just add the result.
1164 Results.push_back(R);
1165 return;
1166 }
1167
Douglas Gregorc580c522010-01-14 01:09:38 +00001168 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +00001169 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001170 CodeCompletionResult Result(Using->getTargetDecl(),
1171 getBasePriority(Using->getTargetDecl()),
1172 R.Qualifier);
1173 Result.ShadowDecl = Using;
1174 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +00001175 return;
1176 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001177
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001178 bool AsNestedNameSpecifier = false;
1179 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +00001180 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001181
Douglas Gregor0212fd72010-09-21 16:06:22 +00001182 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001183 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001184 return;
1185
Douglas Gregorc580c522010-01-14 01:09:38 +00001186 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1187 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001188
Douglas Gregorc580c522010-01-14 01:09:38 +00001189 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001190 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001191 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001192
Douglas Gregorc580c522010-01-14 01:09:38 +00001193 // If the filter is for nested-name-specifiers, then this result starts a
1194 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001195 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001196 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001197 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001198 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1199 InBaseClass &&
1200 isa<CXXRecordDecl>(
1201 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001202 R.QualifierIsInformative = true;
1203
Douglas Gregorc580c522010-01-14 01:09:38 +00001204 // If this result is supposed to have an informative qualifier, add one.
1205 if (R.QualifierIsInformative && !R.Qualifier &&
1206 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001207 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001208 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1209 R.Qualifier =
1210 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1211 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1212 R.Qualifier = NestedNameSpecifier::Create(
1213 SemaRef.Context, nullptr, false,
1214 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001215 else
1216 R.QualifierIsInformative = false;
1217 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001218
Douglas Gregora2db7932010-05-26 22:00:08 +00001219 // Adjust the priority if this result comes from a base class.
1220 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001221 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001222
Douglas Gregor50832e02010-09-20 22:39:41 +00001223 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001224
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001225 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001226 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001227 if (Method->isInstance()) {
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00001228 Qualifiers MethodQuals = Method->getMethodQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001229 if (ObjectTypeQualifiers == MethodQuals)
1230 R.Priority += CCD_ObjectQualifierMatch;
1231 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001232 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001233 // qualifiers.
1234 return;
1235 }
1236 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001237
Douglas Gregorc580c522010-01-14 01:09:38 +00001238 // Insert this result into the set of results.
1239 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001240
Douglas Gregor0212fd72010-09-21 16:06:22 +00001241 if (!AsNestedNameSpecifier)
1242 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001243}
1244
Douglas Gregor78a21012010-01-14 16:01:26 +00001245void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001246 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001247 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001248 Results.push_back(R);
1249}
1250
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001251/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001252void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001253
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001254/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001255void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001256 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00001257 EEnd = ShadowMaps.back().end();
1258 E != EEnd; ++E)
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001259 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001260
Douglas Gregor3545ff42009-09-21 16:56:56 +00001261 ShadowMaps.pop_back();
1262}
1263
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001264/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001265/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001266bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001267 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001268
Richard Smith541b38b2013-09-20 01:15:31 +00001269 // If name lookup finds a local extern declaration, then we are in a
1270 // context where it behaves like an ordinary name.
1271 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001272 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001273 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001274 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001275 if (isa<ObjCIvarDecl>(ND))
1276 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001277 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001278
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001279 return ND->getIdentifierNamespace() & IDNS;
1280}
1281
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001282/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001283/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001284bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001285 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001286 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001287 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001288 // Objective-C interfaces names are not filtered by this method because they
1289 // can be used in a class property expression. We can still filter out
1290 // @class declarations though.
1291 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1292 if (!ID->getDefinition())
1293 return false;
1294 }
1295
Richard Smith541b38b2013-09-20 01:15:31 +00001296 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001297 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001298 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001299 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001300 if (isa<ObjCIvarDecl>(ND))
1301 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001302 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001303
Douglas Gregor70febae2010-05-28 00:49:12 +00001304 return ND->getIdentifierNamespace() & IDNS;
1305}
1306
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001307bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001308 if (!IsOrdinaryNonTypeName(ND))
1309 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001310
Fangrui Song050229d2018-11-24 00:14:31 +00001311 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001312 if (VD->getType()->isIntegralOrEnumerationType())
1313 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001314
Douglas Gregor85b50632010-07-28 21:50:18 +00001315 return false;
1316}
1317
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001318/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001319/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001320bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001321 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001322
Richard Smith541b38b2013-09-20 01:15:31 +00001323 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001324 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001325 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001326
Fangrui Song050229d2018-11-24 00:14:31 +00001327 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1328 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001329}
1330
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001331/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001332/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001333bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001334 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001335 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001336 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001337
Douglas Gregor3545ff42009-09-21 16:56:56 +00001338 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1339}
1340
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001341/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001342bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001343 return isa<EnumDecl>(ND);
1344}
1345
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001346/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001347bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001348 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001349 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001350 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001351
1352 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001353 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1354 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1355 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001356
Douglas Gregor3545ff42009-09-21 16:56:56 +00001357 return false;
1358}
1359
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001360/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001361bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001362 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001363 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001364 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001365
Fangrui Song050229d2018-11-24 00:14:31 +00001366 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001367 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001368
Douglas Gregor3545ff42009-09-21 16:56:56 +00001369 return false;
1370}
1371
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001372/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001373bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001374 return isa<NamespaceDecl>(ND);
1375}
1376
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001377/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001378/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001379bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001380 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001381}
1382
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001383/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001384bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001385 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001386 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001387}
1388
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001389/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001390/// "." or "->". Only value declarations, nested name specifiers, and
1391/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001392bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001393 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001394 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001395 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001396}
1397
Douglas Gregora817a192010-05-27 23:06:34 +00001398static bool isObjCReceiverType(ASTContext &C, QualType T) {
1399 T = C.getCanonicalType(T);
1400 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001401 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001402 case Type::ObjCInterface:
1403 case Type::ObjCObjectPointer:
1404 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001405
Douglas Gregora817a192010-05-27 23:06:34 +00001406 case Type::Builtin:
1407 switch (cast<BuiltinType>(T)->getKind()) {
1408 case BuiltinType::ObjCId:
1409 case BuiltinType::ObjCClass:
1410 case BuiltinType::ObjCSel:
1411 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001412
Douglas Gregora817a192010-05-27 23:06:34 +00001413 default:
1414 break;
1415 }
1416 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001417
Douglas Gregora817a192010-05-27 23:06:34 +00001418 default:
1419 break;
1420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001421
David Blaikiebbafb8a2012-03-11 07:00:24 +00001422 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001423 return false;
1424
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001425 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001426 // particular class type has any conversions to Objective-C types. For now,
1427 // just accept all class types.
1428 return T->isDependentType() || T->isRecordType();
1429}
1430
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001431bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001432 QualType T = getDeclUsageType(SemaRef.Context, ND);
1433 if (T.isNull())
1434 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001435
Douglas Gregora817a192010-05-27 23:06:34 +00001436 T = SemaRef.Context.getBaseElementType(T);
1437 return isObjCReceiverType(SemaRef.Context, T);
1438}
1439
Fangrui Song050229d2018-11-24 00:14:31 +00001440bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1441 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001442 if (IsObjCMessageReceiver(ND))
1443 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001444
Fangrui Song050229d2018-11-24 00:14:31 +00001445 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001446 if (!Var)
1447 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001448
Douglas Gregord8c61782012-02-15 15:34:24 +00001449 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1450}
1451
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001452bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001453 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1454 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001455 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001456
Douglas Gregor68762e72010-08-23 21:17:50 +00001457 QualType T = getDeclUsageType(SemaRef.Context, ND);
1458 if (T.isNull())
1459 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001460
Douglas Gregor68762e72010-08-23 21:17:50 +00001461 T = SemaRef.Context.getBaseElementType(T);
1462 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001463 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001464 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001465}
Douglas Gregora817a192010-05-27 23:06:34 +00001466
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001467bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001468 return false;
1469}
1470
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001471/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001472/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001473bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001474 return isa<ObjCIvarDecl>(ND);
1475}
1476
Douglas Gregorc580c522010-01-14 01:09:38 +00001477namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001478
Fangrui Song050229d2018-11-24 00:14:31 +00001479/// Visible declaration consumer that adds a code-completion result
1480/// for each visible declaration.
1481class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1482 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001483 DeclContext *InitialLookupCtx;
1484 // NamingClass and BaseType are used for access-checking. See
1485 // Sema::IsSimplyAccessible for details.
1486 CXXRecordDecl *NamingClass;
1487 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001488 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001489
Fangrui Song050229d2018-11-24 00:14:31 +00001490public:
1491 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001492 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1493 QualType BaseType = QualType(),
1494 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1495 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1496 FixIts(std::move(FixIts)) {
1497 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1498 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1499 if (BaseType.isNull()) {
1500 auto ThisType = Results.getSema().getCurrentThisType();
1501 if (!ThisType.isNull()) {
1502 assert(ThisType->isPointerType());
1503 BaseType = ThisType->getPointeeType();
1504 if (!NamingClass)
1505 NamingClass = BaseType->getAsCXXRecordDecl();
1506 }
1507 }
1508 this->BaseType = BaseType;
1509 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001510
Fangrui Song050229d2018-11-24 00:14:31 +00001511 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1512 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001513 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001514 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001515 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001516 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001517
Fangrui Song050229d2018-11-24 00:14:31 +00001518 void EnteredContext(DeclContext *Ctx) override {
1519 Results.addVisitedContext(Ctx);
1520 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001521
1522private:
1523 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1524 // Naming class to use for access check. In most cases it was provided
1525 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1526 // for unqualified lookup we fallback to the \p Ctx in which we found the
1527 // member.
1528 auto *NamingClass = this->NamingClass;
1529 QualType BaseType = this->BaseType;
1530 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1531 if (!NamingClass)
1532 NamingClass = Cls;
1533 // When we emulate implicit 'this->' in an unqualified lookup, we might
1534 // end up with an invalid naming class. In that case, we avoid emulating
1535 // 'this->' qualifier to satisfy preconditions of the access checking.
1536 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1537 !NamingClass->isDerivedFrom(Cls)) {
1538 NamingClass = Cls;
1539 BaseType = QualType();
1540 }
1541 } else {
1542 // The decl was found outside the C++ class, so only ObjC access checks
1543 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1544 // out.
1545 NamingClass = nullptr;
1546 BaseType = QualType();
1547 }
1548 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1549 }
Fangrui Song050229d2018-11-24 00:14:31 +00001550};
1551} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001552
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001553/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001554static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001555 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001556 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001557 Results.AddResult(Result("short", CCP_Type));
1558 Results.AddResult(Result("long", CCP_Type));
1559 Results.AddResult(Result("signed", CCP_Type));
1560 Results.AddResult(Result("unsigned", CCP_Type));
1561 Results.AddResult(Result("void", CCP_Type));
1562 Results.AddResult(Result("char", CCP_Type));
1563 Results.AddResult(Result("int", CCP_Type));
1564 Results.AddResult(Result("float", CCP_Type));
1565 Results.AddResult(Result("double", CCP_Type));
1566 Results.AddResult(Result("enum", CCP_Type));
1567 Results.AddResult(Result("struct", CCP_Type));
1568 Results.AddResult(Result("union", CCP_Type));
1569 Results.AddResult(Result("const", CCP_Type));
1570 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001571
Douglas Gregor3545ff42009-09-21 16:56:56 +00001572 if (LangOpts.C99) {
1573 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001574 Results.AddResult(Result("_Complex", CCP_Type));
1575 Results.AddResult(Result("_Imaginary", CCP_Type));
1576 Results.AddResult(Result("_Bool", CCP_Type));
1577 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001578 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001579
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001580 CodeCompletionBuilder Builder(Results.getAllocator(),
1581 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001582 if (LangOpts.CPlusPlus) {
1583 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001584 Results.AddResult(
1585 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001586 Results.AddResult(Result("class", CCP_Type));
1587 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001588
Douglas Gregorf4c33342010-05-28 00:22:41 +00001589 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001590 Builder.AddTypedTextChunk("typename");
1591 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1592 Builder.AddPlaceholderChunk("qualifier");
1593 Builder.AddTextChunk("::");
1594 Builder.AddPlaceholderChunk("name");
1595 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001596
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001597 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001598 Results.AddResult(Result("auto", CCP_Type));
1599 Results.AddResult(Result("char16_t", CCP_Type));
1600 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001601
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001602 Builder.AddTypedTextChunk("decltype");
1603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1604 Builder.AddPlaceholderChunk("expression");
1605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1606 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001607 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001608 } else
1609 Results.AddResult(Result("__auto_type", CCP_Type));
1610
Richard Smith7b301e22018-05-24 21:51:52 +00001611 // GNU keywords
1612 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001613 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001614 // Results.AddResult(Result("_Decimal32"));
1615 // Results.AddResult(Result("_Decimal64"));
1616 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001617
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001618 Builder.AddTypedTextChunk("typeof");
1619 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1620 Builder.AddPlaceholderChunk("expression");
1621 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001622
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001623 Builder.AddTypedTextChunk("typeof");
1624 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1625 Builder.AddPlaceholderChunk("type");
1626 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1627 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001628 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001629
1630 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001631 Results.AddResult(Result("_Nonnull", CCP_Type));
1632 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1633 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001634}
1635
John McCallfaf5fb42010-08-26 23:41:50 +00001636static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001637 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001638 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001639 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001640 // Note: we don't suggest either "auto" or "register", because both
1641 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1642 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001643 Results.AddResult(Result("extern"));
1644 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001645
1646 if (LangOpts.CPlusPlus11) {
1647 CodeCompletionAllocator &Allocator = Results.getAllocator();
1648 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1649
1650 // alignas
1651 Builder.AddTypedTextChunk("alignas");
1652 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1653 Builder.AddPlaceholderChunk("expression");
1654 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1655 Results.AddResult(Result(Builder.TakeString()));
1656
1657 Results.AddResult(Result("constexpr"));
1658 Results.AddResult(Result("thread_local"));
1659 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001660}
1661
John McCallfaf5fb42010-08-26 23:41:50 +00001662static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001663 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001664 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001665 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001666 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001667 case Sema::PCC_Class:
1668 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001669 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001670 Results.AddResult(Result("explicit"));
1671 Results.AddResult(Result("friend"));
1672 Results.AddResult(Result("mutable"));
1673 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001674 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001675 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001676
John McCallfaf5fb42010-08-26 23:41:50 +00001677 case Sema::PCC_ObjCInterface:
1678 case Sema::PCC_ObjCImplementation:
1679 case Sema::PCC_Namespace:
1680 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001681 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001682 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001683 break;
1684
John McCallfaf5fb42010-08-26 23:41:50 +00001685 case Sema::PCC_ObjCInstanceVariableList:
1686 case Sema::PCC_Expression:
1687 case Sema::PCC_Statement:
1688 case Sema::PCC_ForInit:
1689 case Sema::PCC_Condition:
1690 case Sema::PCC_RecoveryInFunction:
1691 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001692 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001693 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001694 break;
1695 }
1696}
1697
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001698static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1699static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1700static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001701 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001702static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001703 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001704static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001705 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001706static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001707
Douglas Gregorf4c33342010-05-28 00:22:41 +00001708static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001709 CodeCompletionBuilder Builder(Results.getAllocator(),
1710 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001711 Builder.AddTypedTextChunk("typedef");
1712 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1713 Builder.AddPlaceholderChunk("type");
1714 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1715 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001716 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001717}
1718
John McCallfaf5fb42010-08-26 23:41:50 +00001719static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001720 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001721 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001722 case Sema::PCC_Namespace:
1723 case Sema::PCC_Class:
1724 case Sema::PCC_ObjCInstanceVariableList:
1725 case Sema::PCC_Template:
1726 case Sema::PCC_MemberTemplate:
1727 case Sema::PCC_Statement:
1728 case Sema::PCC_RecoveryInFunction:
1729 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001730 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001731 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001732 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001733
John McCallfaf5fb42010-08-26 23:41:50 +00001734 case Sema::PCC_Expression:
1735 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001736 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001737
Douglas Gregor5e35d592010-09-14 23:59:36 +00001738 case Sema::PCC_ObjCInterface:
1739 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001740 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001741
John McCallfaf5fb42010-08-26 23:41:50 +00001742 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001743 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001744 }
David Blaikie8a40f702012-01-17 06:56:22 +00001745
1746 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001747}
1748
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001749static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1750 const Preprocessor &PP) {
1751 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001752 Policy.AnonymousTagLocations = false;
1753 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001754 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001755 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001756 return Policy;
1757}
1758
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001759/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001760static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1761 return getCompletionPrintingPolicy(S.Context, S.PP);
1762}
1763
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001764/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001765/// that has the appropriate lifetime for code completion.
1766///
1767/// This routine provides a fast path where we provide constant strings for
1768/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001769static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001770 const PrintingPolicy &Policy,
1771 CodeCompletionAllocator &Allocator) {
1772 if (!T.getLocalQualifiers()) {
1773 // Built-in type names are constant strings.
1774 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001775 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001776
Douglas Gregore5c79d52011-10-18 21:20:17 +00001777 // Anonymous tag types are constant strings.
1778 if (const TagType *TagT = dyn_cast<TagType>(T))
1779 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001780 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001781 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001782 case TTK_Struct:
1783 return "struct <anonymous>";
1784 case TTK_Interface:
1785 return "__interface <anonymous>";
1786 case TTK_Class:
1787 return "class <anonymous>";
1788 case TTK_Union:
1789 return "union <anonymous>";
1790 case TTK_Enum:
1791 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001792 }
1793 }
1794 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001795
Douglas Gregore5c79d52011-10-18 21:20:17 +00001796 // Slow path: format the type as a string.
1797 std::string Result;
1798 T.getAsStringInternal(Result, Policy);
1799 return Allocator.CopyString(Result);
1800}
1801
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001802/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001803static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1804 QualType ThisTy = S.getCurrentThisType();
1805 if (ThisTy.isNull())
1806 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001807
Douglas Gregord8c61782012-02-15 15:34:24 +00001808 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001809 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001810 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001811 Builder.AddResultTypeChunk(
1812 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001813 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001814 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001815}
1816
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001817static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1818 ResultBuilder &Results,
1819 const LangOptions &LangOpts) {
1820 if (!LangOpts.CPlusPlus11)
1821 return;
1822
1823 Builder.AddTypedTextChunk("static_assert");
1824 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1825 Builder.AddPlaceholderChunk("expression");
1826 Builder.AddChunk(CodeCompletionString::CK_Comma);
1827 Builder.AddPlaceholderChunk("message");
1828 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1829 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1830}
1831
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001832static void AddOverrideResults(ResultBuilder &Results,
1833 const CodeCompletionContext &CCContext,
1834 CodeCompletionBuilder &Builder) {
1835 Sema &S = Results.getSema();
1836 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1837 // If not inside a class/struct/union return empty.
1838 if (!CR)
1839 return;
1840 // First store overrides within current class.
1841 // These are stored by name to make querying fast in the later step.
1842 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1843 for (auto *Method : CR->methods()) {
1844 if (!Method->isVirtual() || !Method->getIdentifier())
1845 continue;
1846 Overrides[Method->getName()].push_back(Method);
1847 }
1848
1849 for (const auto &Base : CR->bases()) {
1850 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1851 if (!BR)
1852 continue;
1853 for (auto *Method : BR->methods()) {
1854 if (!Method->isVirtual() || !Method->getIdentifier())
1855 continue;
1856 const auto it = Overrides.find(Method->getName());
1857 bool IsOverriden = false;
1858 if (it != Overrides.end()) {
1859 for (auto *MD : it->second) {
1860 // If the method in current body is not an overload of this virtual
1861 // function, then it overrides this one.
1862 if (!S.IsOverload(MD, Method, false)) {
1863 IsOverriden = true;
1864 break;
1865 }
1866 }
1867 }
1868 if (!IsOverriden) {
1869 // Generates a new CodeCompletionResult by taking this function and
1870 // converting it into an override declaration with only one chunk in the
1871 // final CodeCompletionString as a TypedTextChunk.
1872 std::string OverrideSignature;
1873 llvm::raw_string_ostream OS(OverrideSignature);
1874 CodeCompletionResult CCR(Method, 0);
1875 PrintingPolicy Policy =
1876 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1877 auto *CCS = CCR.createCodeCompletionStringForOverride(
1878 S.getPreprocessor(), S.getASTContext(), Builder,
1879 /*IncludeBriefComments=*/false, CCContext, Policy);
1880 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1881 }
1882 }
1883 }
1884}
1885
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001886/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001887static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1888 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001889 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001890 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001891
John McCall276321a2010-08-25 06:19:51 +00001892 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001893 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001894 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001895 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001896 if (Results.includeCodePatterns()) {
1897 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001898 Builder.AddTypedTextChunk("namespace");
1899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1900 Builder.AddPlaceholderChunk("identifier");
1901 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1902 Builder.AddPlaceholderChunk("declarations");
1903 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1904 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1905 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001906 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001907
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001908 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001909 Builder.AddTypedTextChunk("namespace");
1910 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1911 Builder.AddPlaceholderChunk("name");
1912 Builder.AddChunk(CodeCompletionString::CK_Equal);
1913 Builder.AddPlaceholderChunk("namespace");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001914 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001915 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001916
1917 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001918 Builder.AddTypedTextChunk("using");
1919 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1920 Builder.AddTextChunk("namespace");
1921 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1922 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001923 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001924 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001925
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001926 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001927 Builder.AddTypedTextChunk("asm");
1928 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1929 Builder.AddPlaceholderChunk("string-literal");
1930 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1931 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001932
Douglas Gregorf4c33342010-05-28 00:22:41 +00001933 if (Results.includeCodePatterns()) {
1934 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001935 Builder.AddTypedTextChunk("template");
1936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1937 Builder.AddPlaceholderChunk("declaration");
1938 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001939 } else {
1940 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001941 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001942 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001943
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001944 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001945 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001946
Douglas Gregorf4c33342010-05-28 00:22:41 +00001947 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001948 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001949
John McCallfaf5fb42010-08-26 23:41:50 +00001950 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001951 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001952 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001953 Builder.AddTypedTextChunk("using");
1954 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1955 Builder.AddPlaceholderChunk("qualifier");
1956 Builder.AddTextChunk("::");
1957 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001958 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001959 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001960
Douglas Gregorf4c33342010-05-28 00:22:41 +00001961 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001962 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001963 Builder.AddTypedTextChunk("using");
1964 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1965 Builder.AddTextChunk("typename");
1966 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1967 Builder.AddPlaceholderChunk("qualifier");
1968 Builder.AddTextChunk("::");
1969 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001970 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001971 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001972 }
1973
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001974 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1975
John McCallfaf5fb42010-08-26 23:41:50 +00001976 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001977 AddTypedefResult(Results);
1978
Erik Verbruggen6524c052017-10-24 13:46:58 +00001979 bool IsNotInheritanceScope =
1980 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001981 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001982 Builder.AddTypedTextChunk("public");
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()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001986
1987 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001988 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001989 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001990 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001991 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001992
1993 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001994 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001995 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001996 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001997 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001998
1999 // FIXME: This adds override results only if we are at the first word of
2000 // the declaration/definition. Also call this from other sides to have
2001 // more use-cases.
2002 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
2003 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002004 }
2005 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002006 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002007
John McCallfaf5fb42010-08-26 23:41:50 +00002008 case Sema::PCC_Template:
2009 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002010 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002011 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002012 Builder.AddTypedTextChunk("template");
2013 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2014 Builder.AddPlaceholderChunk("parameters");
2015 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2016 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002017 } else {
2018 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002019 }
2020
David Blaikiebbafb8a2012-03-11 07:00:24 +00002021 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2022 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002023 break;
2024
John McCallfaf5fb42010-08-26 23:41:50 +00002025 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002026 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2027 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2028 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002029 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002030
John McCallfaf5fb42010-08-26 23:41:50 +00002031 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002032 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2033 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2034 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002035 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002036
John McCallfaf5fb42010-08-26 23:41:50 +00002037 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002038 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002039 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002040
John McCallfaf5fb42010-08-26 23:41:50 +00002041 case Sema::PCC_RecoveryInFunction:
2042 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002043 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002044
David Blaikiebbafb8a2012-03-11 07:00:24 +00002045 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2046 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002047 Builder.AddTypedTextChunk("try");
2048 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2049 Builder.AddPlaceholderChunk("statements");
2050 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2051 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2052 Builder.AddTextChunk("catch");
2053 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2054 Builder.AddPlaceholderChunk("declaration");
2055 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2056 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2057 Builder.AddPlaceholderChunk("statements");
2058 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2059 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2060 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002061 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002062 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002063 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002064
Douglas Gregorf64acca2010-05-25 21:41:55 +00002065 if (Results.includeCodePatterns()) {
2066 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002067 Builder.AddTypedTextChunk("if");
2068 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002069 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002070 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002071 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002072 Builder.AddPlaceholderChunk("expression");
2073 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2074 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2075 Builder.AddPlaceholderChunk("statements");
2076 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2077 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2078 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002079
Douglas Gregorf64acca2010-05-25 21:41:55 +00002080 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002081 Builder.AddTypedTextChunk("switch");
2082 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002083 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002084 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002085 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002086 Builder.AddPlaceholderChunk("expression");
2087 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2088 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2089 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2090 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2091 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002092 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002093
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002094 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002095 if (SemaRef.getCurFunction() &&
2096 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002097 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002098 Builder.AddTypedTextChunk("case");
2099 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2100 Builder.AddPlaceholderChunk("expression");
2101 Builder.AddChunk(CodeCompletionString::CK_Colon);
2102 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002103
2104 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002105 Builder.AddTypedTextChunk("default");
2106 Builder.AddChunk(CodeCompletionString::CK_Colon);
2107 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002108 }
2109
Douglas Gregorf64acca2010-05-25 21:41:55 +00002110 if (Results.includeCodePatterns()) {
2111 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002112 Builder.AddTypedTextChunk("while");
2113 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002114 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002115 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002116 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002117 Builder.AddPlaceholderChunk("expression");
2118 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2119 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2120 Builder.AddPlaceholderChunk("statements");
2121 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2122 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2123 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002124
2125 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002126 Builder.AddTypedTextChunk("do");
2127 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2128 Builder.AddPlaceholderChunk("statements");
2129 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2130 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2131 Builder.AddTextChunk("while");
2132 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2133 Builder.AddPlaceholderChunk("expression");
2134 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2135 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002136
Douglas Gregorf64acca2010-05-25 21:41:55 +00002137 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002138 Builder.AddTypedTextChunk("for");
2139 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002140 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002141 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002142 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002143 Builder.AddPlaceholderChunk("init-expression");
2144 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2145 Builder.AddPlaceholderChunk("condition");
2146 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2147 Builder.AddPlaceholderChunk("inc-expression");
2148 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2149 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2150 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2151 Builder.AddPlaceholderChunk("statements");
2152 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2153 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2154 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002155 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002156
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002157 if (S->getContinueParent()) {
2158 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002159 Builder.AddTypedTextChunk("continue");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002160 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002161 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002162 }
2163
2164 if (S->getBreakParent()) {
2165 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002166 Builder.AddTypedTextChunk("break");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002167 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002168 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002169 }
2170
Ilya Biryukov32497f52019-05-27 09:52:09 +00002171 // "return expression ;" or "return ;", depending on the return type.
2172 QualType ReturnType;
Fangrui Song050229d2018-11-24 00:14:31 +00002173 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002174 ReturnType = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002175 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002176 ReturnType = Method->getReturnType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002177 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002178 !SemaRef.getCurBlock()->ReturnType.isNull())
Ilya Biryukov32497f52019-05-27 09:52:09 +00002179 ReturnType = SemaRef.getCurBlock()->ReturnType;;
2180 if (ReturnType.isNull() || ReturnType->isVoidType()) {
2181 Builder.AddTypedTextChunk("return");
2182 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2183 Results.AddResult(Result(Builder.TakeString()));
2184 } else {
2185 assert(!ReturnType.isNull());
2186 // "return expression ;"
2187 Builder.AddTypedTextChunk("return");
2188 Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002189 Builder.AddPlaceholderChunk("expression");
Ilya Biryukov32497f52019-05-27 09:52:09 +00002190 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2191 Results.AddResult(Result(Builder.TakeString()));
2192 // When boolean, also add 'return true;' and 'return false;'.
2193 if (ReturnType->isBooleanType()) {
2194 Builder.AddTypedTextChunk("return true");
2195 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2196 Results.AddResult(Result(Builder.TakeString()));
2197
2198 Builder.AddTypedTextChunk("return false");
2199 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2200 Results.AddResult(Result(Builder.TakeString()));
2201 }
Douglas Gregor44272ca2010-02-18 04:06:48 +00002202 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002203
Douglas Gregorf4c33342010-05-28 00:22:41 +00002204 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002205 Builder.AddTypedTextChunk("goto");
2206 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2207 Builder.AddPlaceholderChunk("label");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002208 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002209 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002210
Douglas Gregorf4c33342010-05-28 00:22:41 +00002211 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002212 Builder.AddTypedTextChunk("using");
2213 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2214 Builder.AddTextChunk("namespace");
2215 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2216 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002217 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002218 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002219
2220 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002221 }
Fangrui Song050229d2018-11-24 00:14:31 +00002222 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002223
2224 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002225 case Sema::PCC_ForInit:
2226 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002227 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002228 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002229 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002230
Douglas Gregor5e35d592010-09-14 23:59:36 +00002231 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002232 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002233 CCC == Sema::PCC_ParenthesizedExpression) {
2234 // (__bridge <type>)<expression>
2235 Builder.AddTypedTextChunk("__bridge");
2236 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2237 Builder.AddPlaceholderChunk("type");
2238 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2239 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002240 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002241
2242 // (__bridge_transfer <Objective-C type>)<expression>
2243 Builder.AddTypedTextChunk("__bridge_transfer");
2244 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2245 Builder.AddPlaceholderChunk("Objective-C type");
2246 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2247 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002248 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002249
2250 // (__bridge_retained <CF type>)<expression>
2251 Builder.AddTypedTextChunk("__bridge_retained");
2252 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2253 Builder.AddPlaceholderChunk("CF type");
2254 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2255 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002256 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002257 }
2258 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002259 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002260
John McCallfaf5fb42010-08-26 23:41:50 +00002261 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002262 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002263 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002264 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002265
Douglas Gregore5c79d52011-10-18 21:20:17 +00002266 // true
2267 Builder.AddResultTypeChunk("bool");
2268 Builder.AddTypedTextChunk("true");
2269 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002270
Douglas Gregore5c79d52011-10-18 21:20:17 +00002271 // false
2272 Builder.AddResultTypeChunk("bool");
2273 Builder.AddTypedTextChunk("false");
2274 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002275
David Blaikiebbafb8a2012-03-11 07:00:24 +00002276 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002277 // dynamic_cast < type-id > ( expression )
2278 Builder.AddTypedTextChunk("dynamic_cast");
2279 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2280 Builder.AddPlaceholderChunk("type");
2281 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2282 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2283 Builder.AddPlaceholderChunk("expression");
2284 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002285 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002286 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002287
Douglas Gregorf4c33342010-05-28 00:22:41 +00002288 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002289 Builder.AddTypedTextChunk("static_cast");
2290 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2291 Builder.AddPlaceholderChunk("type");
2292 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2293 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2294 Builder.AddPlaceholderChunk("expression");
2295 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002296 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002297
Douglas Gregorf4c33342010-05-28 00:22:41 +00002298 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002299 Builder.AddTypedTextChunk("reinterpret_cast");
2300 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2301 Builder.AddPlaceholderChunk("type");
2302 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2303 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2304 Builder.AddPlaceholderChunk("expression");
2305 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002306 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002307
Douglas Gregorf4c33342010-05-28 00:22:41 +00002308 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002309 Builder.AddTypedTextChunk("const_cast");
2310 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2311 Builder.AddPlaceholderChunk("type");
2312 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2313 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2314 Builder.AddPlaceholderChunk("expression");
2315 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002316 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002317
David Blaikiebbafb8a2012-03-11 07:00:24 +00002318 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002319 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002320 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002321 Builder.AddTypedTextChunk("typeid");
2322 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2323 Builder.AddPlaceholderChunk("expression-or-type");
2324 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002325 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002326 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002327
Douglas Gregorf4c33342010-05-28 00:22:41 +00002328 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002329 Builder.AddTypedTextChunk("new");
2330 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2331 Builder.AddPlaceholderChunk("type");
2332 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2333 Builder.AddPlaceholderChunk("expressions");
2334 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002335 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002336
Douglas Gregorf4c33342010-05-28 00:22:41 +00002337 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002338 Builder.AddTypedTextChunk("new");
2339 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2340 Builder.AddPlaceholderChunk("type");
2341 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2342 Builder.AddPlaceholderChunk("size");
2343 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2344 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2345 Builder.AddPlaceholderChunk("expressions");
2346 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002347 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002348
Douglas Gregorf4c33342010-05-28 00:22:41 +00002349 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002350 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002351 Builder.AddTypedTextChunk("delete");
2352 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2353 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002354 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002355
Douglas Gregorf4c33342010-05-28 00:22:41 +00002356 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002357 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002358 Builder.AddTypedTextChunk("delete");
2359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2360 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2361 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2362 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2363 Builder.AddPlaceholderChunk("expression");
2364 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002365
David Blaikiebbafb8a2012-03-11 07:00:24 +00002366 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002367 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002368 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002369 Builder.AddTypedTextChunk("throw");
2370 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2371 Builder.AddPlaceholderChunk("expression");
2372 Results.AddResult(Result(Builder.TakeString()));
2373 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002374
Douglas Gregora2db7932010-05-26 22:00:08 +00002375 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002376
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002377 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002378 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002379 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002380 Builder.AddTypedTextChunk("nullptr");
2381 Results.AddResult(Result(Builder.TakeString()));
2382
2383 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002384 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002385 Builder.AddTypedTextChunk("alignof");
2386 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2387 Builder.AddPlaceholderChunk("type");
2388 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2389 Results.AddResult(Result(Builder.TakeString()));
2390
2391 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002392 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002393 Builder.AddTypedTextChunk("noexcept");
2394 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2395 Builder.AddPlaceholderChunk("expression");
2396 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2397 Results.AddResult(Result(Builder.TakeString()));
2398
2399 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002400 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002401 Builder.AddTypedTextChunk("sizeof...");
2402 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2403 Builder.AddPlaceholderChunk("parameter-pack");
2404 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2405 Results.AddResult(Result(Builder.TakeString()));
2406 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002407 }
2408
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002409 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002410 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002411 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2412 // The interface can be NULL.
2413 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002414 if (ID->getSuperClass()) {
2415 std::string SuperType;
2416 SuperType = ID->getSuperClass()->getNameAsString();
2417 if (Method->isInstanceMethod())
2418 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002419
Douglas Gregore5c79d52011-10-18 21:20:17 +00002420 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2421 Builder.AddTypedTextChunk("super");
2422 Results.AddResult(Result(Builder.TakeString()));
2423 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002424 }
2425
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002426 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002427 }
2428
Jordan Rose58d54722012-06-30 21:33:57 +00002429 if (SemaRef.getLangOpts().C11) {
2430 // _Alignof
2431 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002432 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002433 Builder.AddTypedTextChunk("alignof");
2434 else
2435 Builder.AddTypedTextChunk("_Alignof");
2436 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2437 Builder.AddPlaceholderChunk("type");
2438 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2439 Results.AddResult(Result(Builder.TakeString()));
2440 }
2441
Douglas Gregorf4c33342010-05-28 00:22:41 +00002442 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002443 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002444 Builder.AddTypedTextChunk("sizeof");
2445 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2446 Builder.AddPlaceholderChunk("expression-or-type");
2447 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2448 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002449 break;
2450 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002451
John McCallfaf5fb42010-08-26 23:41:50 +00002452 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002453 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002454 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002455 }
2456
David Blaikiebbafb8a2012-03-11 07:00:24 +00002457 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2458 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002459
David Blaikiebbafb8a2012-03-11 07:00:24 +00002460 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002461 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002462}
2463
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002464/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002465/// type chunk.
2466static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002467 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002468 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002469 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002470 if (!ND)
2471 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002472
2473 // Skip constructors and conversion functions, which have their return types
2474 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002475 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002476 return;
2477
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002478 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002479 QualType T;
2480 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002481 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002482 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002483 if (!BaseType.isNull())
2484 T = Method->getSendResultType(BaseType);
2485 else
2486 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002487 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002488 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002489 T = clang::TypeName::getFullyQualifiedType(T, Context);
2490 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002491 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002492 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002493 if (!BaseType.isNull())
2494 T = Ivar->getUsageType(BaseType);
2495 else
2496 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002497 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002498 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002499 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002500 if (!BaseType.isNull())
2501 T = Property->getUsageType(BaseType);
2502 else
2503 T = Property->getType();
2504 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002505
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002506 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2507 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002508
Fangrui Song050229d2018-11-24 00:14:31 +00002509 Result.AddResultTypeChunk(
2510 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002511}
2512
Richard Smith20e883e2015-04-29 23:20:19 +00002513static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002514 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002515 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002516 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2517 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002518 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002519 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002520 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002521 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002522 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002523 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002524 }
2525}
2526
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002527static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002528 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002529 std::string Result;
2530 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002531 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002532 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002533 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002534 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002535 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002536 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002537 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002538 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002539 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002540 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002541 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002542 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2543 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2544 switch (*nullability) {
2545 case NullabilityKind::NonNull:
2546 Result += "nonnull ";
2547 break;
2548
2549 case NullabilityKind::Nullable:
2550 Result += "nullable ";
2551 break;
2552
2553 case NullabilityKind::Unspecified:
2554 Result += "null_unspecified ";
2555 break;
2556 }
2557 }
2558 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002559 return Result;
2560}
2561
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002562/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002563/// block placeholder.
2564///
2565/// This function ignores things like typedefs and qualifiers in order to
2566/// present the most relevant and accurate block placeholders in code completion
2567/// results.
2568static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2569 FunctionTypeLoc &Block,
2570 FunctionProtoTypeLoc &BlockProto,
2571 bool SuppressBlock = false) {
2572 if (!TSInfo)
2573 return;
2574 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2575 while (true) {
2576 // Look through typedefs.
2577 if (!SuppressBlock) {
2578 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2579 if (TypeSourceInfo *InnerTSInfo =
2580 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2581 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2582 continue;
2583 }
2584 }
2585
2586 // Look through qualified types
2587 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2588 TL = QualifiedTL.getUnqualifiedLoc();
2589 continue;
2590 }
2591
2592 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2593 TL = AttrTL.getModifiedLoc();
2594 continue;
2595 }
2596 }
2597
2598 // Try to get the function prototype behind the block pointer type,
2599 // then we're done.
2600 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2601 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2602 Block = TL.getAs<FunctionTypeLoc>();
2603 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2604 }
2605 break;
2606 }
2607}
2608
Alex Lorenz920ae142016-10-18 10:38:58 +00002609static std::string
2610formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2611 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002612 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002613 bool SuppressBlock = false,
2614 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2615
Fangrui Song050229d2018-11-24 00:14:31 +00002616static std::string
2617FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2618 bool SuppressName = false, bool SuppressBlock = false,
2619 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Sam McCallbc7ff892019-04-04 11:34:18 +00002620 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.
2621 // It would be better to pass in the param Type, which is usually avaliable.
2622 // But this case is rare, so just pretend we fell back to int as elsewhere.
2623 if (!Param)
2624 return "int";
Douglas Gregore90dd002010-08-24 16:15:59 +00002625 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2626 if (Param->getType()->isDependentType() ||
2627 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002628 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002629 // containing that parameter's type.
2630 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002631
Douglas Gregor981a0c42010-08-29 19:47:46 +00002632 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002633 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002634
Douglas Gregor86b42682015-06-19 18:27:52 +00002635 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002636 if (ObjCSubsts)
2637 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2638 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002639 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002640 Result =
2641 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002642 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002643 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002644 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002645 } else {
2646 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002647 }
2648 return Result;
2649 }
Alex Lorenza1951202016-10-18 10:35:27 +00002650
Douglas Gregore90dd002010-08-24 16:15:59 +00002651 // The argument for a block pointer parameter is a block literal with
2652 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002653 FunctionTypeLoc Block;
2654 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002655 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2656 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002657 // Try to retrieve the block type information from the property if this is a
2658 // parameter in a setter.
2659 if (!Block && ObjCMethodParam &&
2660 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2661 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2662 ->findPropertyDecl(/*CheckOverrides=*/false))
2663 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2664 SuppressBlock);
2665 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002666
2667 if (!Block) {
2668 // We were unable to find a FunctionProtoTypeLoc with parameter names
2669 // for the block; just use the parameter type as a placeholder.
2670 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002671 if (!ObjCMethodParam && Param->getIdentifier())
2672 Result = Param->getIdentifier()->getName();
2673
Douglas Gregor86b42682015-06-19 18:27:52 +00002674 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002675
Douglas Gregore90dd002010-08-24 16:15:59 +00002676 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002677 Result = Type.getAsString(Policy);
2678 std::string Quals =
2679 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2680 if (!Quals.empty())
2681 Result = "(" + Quals + " " + Result + ")";
2682 if (Result.back() != ')')
2683 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002684 if (Param->getIdentifier())
2685 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002686 } else {
2687 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002688 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002689
Douglas Gregore90dd002010-08-24 16:15:59 +00002690 return Result;
2691 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002692
Douglas Gregore90dd002010-08-24 16:15:59 +00002693 // We have the function prototype behind the block pointer type, as it was
2694 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002695 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2696 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002697 ObjCSubsts);
2698}
2699
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002700/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002701/// declaration.
2702///
2703/// \param BlockDecl A declaration with an Objective-C block type.
2704///
2705/// \param Block The most relevant type location for that block type.
2706///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002707/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002708/// declaration is included in the resulting string.
2709static std::string
2710formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2711 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002712 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002713 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002714 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002715 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002716 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002717 ResultType =
2718 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2719 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002720 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002721 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002722
2723 // Format the parameter list.
2724 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002725 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002726 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002727 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002728 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002729 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002730 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002731 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002732 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002733 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002734 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002735 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002736 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002737 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002738
David Blaikie6adc78e2013-02-18 22:06:02 +00002739 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002740 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002741 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002742 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002743 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002744
Douglas Gregord793e7c2011-10-18 04:23:19 +00002745 if (SuppressBlock) {
2746 // Format as a parameter.
2747 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002748 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002749 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002750 Result += ")";
2751 Result += Params;
2752 } else {
2753 // Format as a block literal argument.
2754 Result = '^' + Result;
2755 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002756
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002757 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002758 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002759 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002760
Douglas Gregore90dd002010-08-24 16:15:59 +00002761 return Result;
2762}
2763
Erik Verbruggen11338c52017-07-19 10:45:40 +00002764static std::string GetDefaultValueString(const ParmVarDecl *Param,
2765 const SourceManager &SM,
2766 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002767 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002768 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2769 bool Invalid = CharSrcRange.isInvalid();
2770 if (Invalid)
2771 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002772 StringRef srcText =
2773 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002774 if (Invalid)
2775 return "";
2776
2777 if (srcText.empty() || srcText == "=") {
2778 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002779 // This happens if the code is incorrect (for example class is forward
2780 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002781 return "";
2782 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002783 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002784 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2785 // this value always has (or always does not have) '=' in front of it
2786 if (DefValue.at(0) != '=') {
2787 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002788 // Lexer returns built-in types values without '=' and user-defined types
2789 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002790 return " = " + DefValue;
2791 }
2792 return " " + DefValue;
2793}
2794
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002795/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002796static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002797 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002798 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002799 CodeCompletionBuilder &Result,
2800 unsigned Start = 0,
2801 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002802 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002803
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002804 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002805 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002806
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002807 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002808 // When we see an optional default argument, put that argument and
2809 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002810 CodeCompletionBuilder Opt(Result.getAllocator(),
2811 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002812 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002813 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002814 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002815 Result.AddOptionalChunk(Opt.TakeString());
2816 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002817 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002818
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002819 if (FirstParameter)
2820 FirstParameter = false;
2821 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002822 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002823
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002824 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002825
Douglas Gregor3545ff42009-09-21 16:56:56 +00002826 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002827 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002828 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002829 PlaceholderStr +=
2830 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002831
Douglas Gregor400f5972010-08-31 05:13:43 +00002832 if (Function->isVariadic() && P == N - 1)
2833 PlaceholderStr += ", ...";
2834
Douglas Gregor3545ff42009-09-21 16:56:56 +00002835 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002836 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002837 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002838 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002839
Fangrui Song050229d2018-11-24 00:14:31 +00002840 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002841 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002842 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002843 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002844
Richard Smith20e883e2015-04-29 23:20:19 +00002845 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002846 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002847}
2848
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002849/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002850static void AddTemplateParameterChunks(
2851 ASTContext &Context, const PrintingPolicy &Policy,
2852 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2853 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002854 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002855
2856 // Prefer to take the template parameter names from the first declaration of
2857 // the template.
2858 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2859
Douglas Gregor3545ff42009-09-21 16:56:56 +00002860 TemplateParameterList *Params = Template->getTemplateParameters();
2861 TemplateParameterList::iterator PEnd = Params->end();
2862 if (MaxParameters)
2863 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002864 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2865 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002866 bool HasDefaultArg = false;
2867 std::string PlaceholderStr;
2868 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2869 if (TTP->wasDeclaredWithTypename())
2870 PlaceholderStr = "typename";
2871 else
2872 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002873
Douglas Gregor3545ff42009-09-21 16:56:56 +00002874 if (TTP->getIdentifier()) {
2875 PlaceholderStr += ' ';
2876 PlaceholderStr += TTP->getIdentifier()->getName();
2877 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002878
Douglas Gregor3545ff42009-09-21 16:56:56 +00002879 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002880 } else if (NonTypeTemplateParmDecl *NTTP =
2881 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002882 if (NTTP->getIdentifier())
2883 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002884 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002885 HasDefaultArg = NTTP->hasDefaultArgument();
2886 } else {
2887 assert(isa<TemplateTemplateParmDecl>(*P));
2888 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002889
Douglas Gregor3545ff42009-09-21 16:56:56 +00002890 // Since putting the template argument list into the placeholder would
2891 // be very, very long, we just use an abbreviation.
2892 PlaceholderStr = "template<...> class";
2893 if (TTP->getIdentifier()) {
2894 PlaceholderStr += ' ';
2895 PlaceholderStr += TTP->getIdentifier()->getName();
2896 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002897
Douglas Gregor3545ff42009-09-21 16:56:56 +00002898 HasDefaultArg = TTP->hasDefaultArgument();
2899 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002900
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002901 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002902 // When we see an optional default argument, put that argument and
2903 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002904 CodeCompletionBuilder Opt(Result.getAllocator(),
2905 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002906 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002907 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002908 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002909 P - Params->begin(), true);
2910 Result.AddOptionalChunk(Opt.TakeString());
2911 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002912 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002913
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002914 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002915
Douglas Gregor3545ff42009-09-21 16:56:56 +00002916 if (FirstParameter)
2917 FirstParameter = false;
2918 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002919 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002920
Douglas Gregor3545ff42009-09-21 16:56:56 +00002921 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002922 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002923 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002924 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002925}
2926
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002927/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002928/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002929static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2930 NestedNameSpecifier *Qualifier,
2931 bool QualifierIsInformative,
2932 ASTContext &Context,
2933 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002934 if (!Qualifier)
2935 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002936
Douglas Gregorf2510672009-09-21 19:57:38 +00002937 std::string PrintedNNS;
2938 {
2939 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002940 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002941 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002942 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002943 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002944 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002945 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002946}
2947
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002948static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002949AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002950 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002951 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002952 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00002953 return;
2954
Douglas Gregor304f9b02011-02-01 21:15:40 +00002955 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002956
Douglas Gregor304f9b02011-02-01 21:15:40 +00002957 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002958 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002959 Result.AddInformativeChunk(" const");
2960 return;
2961 }
2962
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002963 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002964 Result.AddInformativeChunk(" volatile");
2965 return;
2966 }
2967
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002968 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002969 Result.AddInformativeChunk(" restrict");
2970 return;
2971 }
2972
2973 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002974 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002975 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002976 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002977 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002978 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002979 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002980 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002981 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002982}
2983
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002984/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002985static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002986 const NamedDecl *ND,
2987 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002988 DeclarationName Name = ND->getDeclName();
2989 if (!Name)
2990 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002991
Douglas Gregor0212fd72010-09-21 16:06:22 +00002992 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002993 case DeclarationName::CXXOperatorName: {
2994 const char *OperatorName = nullptr;
2995 switch (Name.getCXXOverloadedOperator()) {
2996 case OO_None:
2997 case OO_Conditional:
2998 case NUM_OVERLOADED_OPERATORS:
2999 OperatorName = "operator";
3000 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003001
Fangrui Song050229d2018-11-24 00:14:31 +00003002#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
3003 case OO_##Name: \
3004 OperatorName = "operator" Spelling; \
3005 break;
3006#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00003007#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003008
Fangrui Song050229d2018-11-24 00:14:31 +00003009 case OO_New:
3010 OperatorName = "operator new";
3011 break;
3012 case OO_Delete:
3013 OperatorName = "operator delete";
3014 break;
3015 case OO_Array_New:
3016 OperatorName = "operator new[]";
3017 break;
3018 case OO_Array_Delete:
3019 OperatorName = "operator delete[]";
3020 break;
3021 case OO_Call:
3022 OperatorName = "operator()";
3023 break;
3024 case OO_Subscript:
3025 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003026 break;
3027 }
Fangrui Song050229d2018-11-24 00:14:31 +00003028 Result.AddTypedTextChunk(OperatorName);
3029 break;
3030 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003031
Douglas Gregor0212fd72010-09-21 16:06:22 +00003032 case DeclarationName::Identifier:
3033 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003034 case DeclarationName::CXXDestructorName:
3035 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003036 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003037 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003038 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003039
Richard Smith35845152017-02-07 01:37:30 +00003040 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003041 case DeclarationName::CXXUsingDirective:
3042 case DeclarationName::ObjCZeroArgSelector:
3043 case DeclarationName::ObjCOneArgSelector:
3044 case DeclarationName::ObjCMultiArgSelector:
3045 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003046
Douglas Gregor0212fd72010-09-21 16:06:22 +00003047 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003048 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003049 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003050 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003051 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003052 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003053 Record = InjectedTy->getDecl();
3054 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003055 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003056 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003057 break;
3058 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003059
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003060 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003061 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003062 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003063 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003064 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003065 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003066 }
3067 break;
3068 }
3069 }
3070}
3071
Fangrui Song050229d2018-11-24 00:14:31 +00003072CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3073 Sema &S, const CodeCompletionContext &CCContext,
3074 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3075 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003076 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3077 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003078}
3079
Eric Liu00f43c92018-07-06 09:43:57 +00003080CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3081 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3082 CodeCompletionTUInfo &CCTUInfo) {
3083 assert(Kind == RK_Macro);
3084 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3085 const MacroInfo *MI = PP.getMacroInfo(Macro);
3086 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3087
3088 if (!MI || !MI->isFunctionLike())
3089 return Result.TakeString();
3090
3091 // Format a function-like macro with placeholders for the arguments.
3092 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3093 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3094
3095 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3096 if (MI->isC99Varargs()) {
3097 --AEnd;
3098
3099 if (A == AEnd) {
3100 Result.AddPlaceholderChunk("...");
3101 }
3102 }
3103
3104 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3105 if (A != MI->param_begin())
3106 Result.AddChunk(CodeCompletionString::CK_Comma);
3107
3108 if (MI->isVariadic() && (A + 1) == AEnd) {
3109 SmallString<32> Arg = (*A)->getName();
3110 if (MI->isC99Varargs())
3111 Arg += ", ...";
3112 else
3113 Arg += "...";
3114 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3115 break;
3116 }
3117
3118 // Non-variadic macros are simple.
3119 Result.AddPlaceholderChunk(
3120 Result.getAllocator().CopyString((*A)->getName()));
3121 }
3122 Result.AddChunk(CodeCompletionString::CK_RightParen);
3123 return Result.TakeString();
3124}
3125
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003126/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003127/// result.
3128///
3129/// \returns Either a new, heap-allocated code completion string describing
3130/// how to use this result, or NULL to indicate that the string or name of the
3131/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003132CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3133 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3134 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3135 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003136 if (Kind == RK_Macro)
3137 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3138
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003139 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003140
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003141 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003142 if (Kind == RK_Pattern) {
3143 Pattern->Priority = Priority;
3144 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003145
Douglas Gregor78254c82012-03-27 23:34:16 +00003146 if (Declaration) {
3147 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003148 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003149 if (const RawComment *RC =
3150 getPatternCompletionComment(Ctx, Declaration)) {
3151 Result.addBriefComment(RC->getBriefText(Ctx));
3152 Pattern->BriefComment = Result.getBriefComment();
3153 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003154 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003155
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003156 return Pattern;
3157 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003158
Douglas Gregorf09935f2009-12-01 05:55:20 +00003159 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003160 Result.AddTypedTextChunk(Keyword);
3161 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003162 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003163 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003164 return createCodeCompletionStringForDecl(
3165 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003166}
3167
Ilya Biryukovcabab292019-05-24 10:18:39 +00003168static void printOverrideString(const CodeCompletionString &CCS,
3169 std::string &BeforeName,
3170 std::string &NameAndSignature) {
3171 bool SeenTypedChunk = false;
3172 for (auto &Chunk : CCS) {
3173 if (Chunk.Kind == CodeCompletionString::CK_Optional) {
3174 assert(SeenTypedChunk && "optional parameter before name");
3175 // Note that we put all chunks inside into NameAndSignature.
3176 printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature);
3177 continue;
3178 }
3179 SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText;
3180 if (SeenTypedChunk)
3181 NameAndSignature += Chunk.Text;
3182 else
3183 BeforeName += Chunk.Text;
3184 }
3185}
3186
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003187CodeCompletionString *
3188CodeCompletionResult::createCodeCompletionStringForOverride(
3189 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3190 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3191 PrintingPolicy &Policy) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003192 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3193 /*IncludeBriefComments=*/false,
3194 CCContext, Policy);
Ilya Biryukovcabab292019-05-24 10:18:39 +00003195 std::string BeforeName;
3196 std::string NameAndSignature;
3197 // For overrides all chunks go into the result, none are informative.
3198 printOverrideString(*CCS, BeforeName, NameAndSignature);
3199 NameAndSignature += " override";
3200
3201 Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));
3202 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3203 Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003204 return Result.TakeString();
3205}
3206
3207CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3208 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3209 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3210 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003211 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003212 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003213
3214 if (IncludeBriefComments) {
3215 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003216 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003217 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003218 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003219 }
3220
Douglas Gregor9eb77012009-11-07 00:00:49 +00003221 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003222 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003223 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003224 Result.AddTextChunk("::");
3225 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003226 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003227
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003228 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3229 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003230
Douglas Gregorc3425b12015-07-07 06:20:19 +00003231 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003232
Fangrui Song050229d2018-11-24 00:14:31 +00003233 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003234 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003235 Ctx, Policy);
3236 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003237 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003238 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003239 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003240 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003241 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003242 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003243
Fangrui Song050229d2018-11-24 00:14:31 +00003244 if (const FunctionTemplateDecl *FunTmpl =
3245 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003246 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003247 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003248 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003249 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003250
Douglas Gregor3545ff42009-09-21 16:56:56 +00003251 // Figure out which template parameters are deduced (or have default
3252 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003253 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003254 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003255 unsigned LastDeducibleArgument;
3256 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3257 --LastDeducibleArgument) {
3258 if (!Deduced[LastDeducibleArgument - 1]) {
3259 // C++0x: Figure out if the template argument has a default. If so,
3260 // the user doesn't need to type this argument.
3261 // FIXME: We need to abstract template parameters better!
3262 bool HasDefaultArg = false;
3263 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003264 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003265 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3266 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003267 else if (NonTypeTemplateParmDecl *NTTP =
3268 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003269 HasDefaultArg = NTTP->hasDefaultArgument();
3270 else {
3271 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003272 HasDefaultArg =
3273 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003274 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003275
Douglas Gregor3545ff42009-09-21 16:56:56 +00003276 if (!HasDefaultArg)
3277 break;
3278 }
3279 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003280
Douglas Gregor3545ff42009-09-21 16:56:56 +00003281 if (LastDeducibleArgument) {
3282 // Some of the function template arguments cannot be deduced from a
3283 // function call, so we introduce an explicit template argument list
3284 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003285 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003286 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003287 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003288 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003289 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003290
Douglas Gregor3545ff42009-09-21 16:56:56 +00003291 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003292 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003293 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003294 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003295 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003296 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003297 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003298
Fangrui Song050229d2018-11-24 00:14:31 +00003299 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003300 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003301 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003302 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003303 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003304 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003305 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003306 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003307 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003308 }
Fangrui Song050229d2018-11-24 00:14:31 +00003309 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003310 Selector Sel = Method->getSelector();
3311 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003312 Result.AddTypedTextChunk(
3313 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003314 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003315 }
3316
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003317 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003318 SelName += ':';
3319 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003320 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003321 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003322 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003323
Douglas Gregor1b605f72009-11-19 01:08:35 +00003324 // If there is only one parameter, and we're past it, add an empty
3325 // typed-text chunk since there is nothing to type.
3326 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003327 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003328 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003329 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003330 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003331 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003332 P != PEnd; (void)++P, ++Idx) {
3333 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003334 std::string Keyword;
3335 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003336 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003337 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003338 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003339 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003340 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003341 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003342 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003343 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003344 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003345
Douglas Gregor1b605f72009-11-19 01:08:35 +00003346 // If we're before the starting parameter, skip the placeholder.
3347 if (Idx < StartParameter)
3348 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003349
3350 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003351 QualType ParamType = (*P)->getType();
3352 Optional<ArrayRef<QualType>> ObjCSubsts;
3353 if (!CCContext.getBaseType().isNull())
3354 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3355
3356 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3357 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003358 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003359 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003360 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003361 ParamType = ParamType.substObjCTypeArgs(
3362 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003363 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003364 ParamType);
3365 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003366 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003367 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003368 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003369 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003370
Douglas Gregor400f5972010-08-31 05:13:43 +00003371 if (Method->isVariadic() && (P + 1) == PEnd)
3372 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003373
Douglas Gregor95887f92010-07-08 23:20:03 +00003374 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003375 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003376 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003377 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003378 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003379 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003380 }
3381
Douglas Gregor04c5f972009-12-23 00:21:46 +00003382 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003383 if (Method->param_size() == 0) {
3384 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003385 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003386 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003387 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003388 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003389 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003390 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003391
Richard Smith20e883e2015-04-29 23:20:19 +00003392 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003393 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003394
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003395 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003396 }
3397
Douglas Gregorf09935f2009-12-01 05:55:20 +00003398 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003399 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003400 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003401
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003402 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003403 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003404 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003405}
3406
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003407const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3408 const NamedDecl *ND) {
3409 if (!ND)
3410 return nullptr;
3411 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3412 return RC;
3413
3414 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003415 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003416 if (!M)
3417 return nullptr;
3418 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3419 if (!PDecl)
3420 return nullptr;
3421
3422 return Ctx.getRawCommentForAnyRedecl(PDecl);
3423}
3424
3425const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3426 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003427 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003428 if (!M || !M->isPropertyAccessor())
3429 return nullptr;
3430
3431 // Provide code completion comment for self.GetterName where
3432 // GetterName is the getter method for a property with name
3433 // different from the property name (declared via a property
3434 // getter attribute.
3435 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3436 if (!PDecl)
3437 return nullptr;
3438 if (PDecl->getGetterName() == M->getSelector() &&
3439 PDecl->getIdentifier() != M->getIdentifier()) {
3440 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3441 return RC;
3442 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3443 return RC;
3444 }
3445 return nullptr;
3446}
3447
3448const RawComment *clang::getParameterComment(
3449 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003450 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003451 auto FDecl = Result.getFunction();
3452 if (!FDecl)
3453 return nullptr;
3454 if (ArgIndex < FDecl->getNumParams())
3455 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3456 return nullptr;
3457}
3458
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003459/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003460/// string.
3461static void AddOverloadParameterChunks(ASTContext &Context,
3462 const PrintingPolicy &Policy,
3463 const FunctionDecl *Function,
3464 const FunctionProtoType *Prototype,
3465 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003466 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003467 bool InOptional = false) {
3468 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003469 unsigned NumParams =
3470 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003471
3472 for (unsigned P = Start; P != NumParams; ++P) {
3473 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3474 // When we see an optional default argument, put that argument and
3475 // the remaining default arguments into a new, optional string.
3476 CodeCompletionBuilder Opt(Result.getAllocator(),
3477 Result.getCodeCompletionTUInfo());
3478 if (!FirstParameter)
3479 Opt.AddChunk(CodeCompletionString::CK_Comma);
3480 // Optional sections are nested.
3481 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3482 CurrentArg, P, /*InOptional=*/true);
3483 Result.AddOptionalChunk(Opt.TakeString());
3484 return;
3485 }
3486
3487 if (FirstParameter)
3488 FirstParameter = false;
3489 else
3490 Result.AddChunk(CodeCompletionString::CK_Comma);
3491
3492 InOptional = false;
3493
3494 // Format the placeholder string.
3495 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003496 if (Function) {
3497 const ParmVarDecl *Param = Function->getParamDecl(P);
3498 Placeholder = FormatFunctionParameter(Policy, Param);
3499 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003500 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3501 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003502 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003503 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003504 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003505
3506 if (P == CurrentArg)
3507 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003508 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003509 else
3510 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3511 }
3512
3513 if (Prototype && Prototype->isVariadic()) {
3514 CodeCompletionBuilder Opt(Result.getAllocator(),
3515 Result.getCodeCompletionTUInfo());
3516 if (!FirstParameter)
3517 Opt.AddChunk(CodeCompletionString::CK_Comma);
3518
3519 if (CurrentArg < NumParams)
3520 Opt.AddPlaceholderChunk("...");
3521 else
3522 Opt.AddCurrentParameterChunk("...");
3523
3524 Result.AddOptionalChunk(Opt.TakeString());
3525 }
3526}
3527
Douglas Gregorf0f51982009-09-23 00:34:09 +00003528CodeCompletionString *
3529CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003530 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3531 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003532 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003533
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003534 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003535 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3536 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003537 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003538 const FunctionProtoType *Proto =
3539 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003540 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003541 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003542 // highlighted ellipsis.
3543 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003544 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003545 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003546 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3547 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3548 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003549 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003550 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003551
3552 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003553 if (IncludeBriefComments) {
3554 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003555 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003556 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003557 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003558 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003559 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003560 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003561 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003562 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003563 }
Alp Toker314cc812014-01-25 16:55:45 +00003564
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003565 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003566 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3567 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003568 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003569
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003570 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003571}
3572
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003573unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003574 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003575 bool PreferredTypeIsPointer) {
3576 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003577
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003578 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003579 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003580 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003581 Priority = CCP_Constant;
3582 if (PreferredTypeIsPointer)
3583 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003584 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003585 // Treat "YES", "NO", "true", and "false" as constants.
3586 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3587 MacroName.equals("true") || MacroName.equals("false"))
3588 Priority = CCP_Constant;
3589 // Treat "bool" as a type.
3590 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003591 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003592
Douglas Gregor6e240332010-08-16 16:18:59 +00003593 return Priority;
3594}
3595
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003596CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003597 if (!D)
3598 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003599
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003600 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003601 case Decl::Enum:
3602 return CXCursor_EnumDecl;
3603 case Decl::EnumConstant:
3604 return CXCursor_EnumConstantDecl;
3605 case Decl::Field:
3606 return CXCursor_FieldDecl;
3607 case Decl::Function:
3608 return CXCursor_FunctionDecl;
3609 case Decl::ObjCCategory:
3610 return CXCursor_ObjCCategoryDecl;
3611 case Decl::ObjCCategoryImpl:
3612 return CXCursor_ObjCCategoryImplDecl;
3613 case Decl::ObjCImplementation:
3614 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003615
Fangrui Song050229d2018-11-24 00:14:31 +00003616 case Decl::ObjCInterface:
3617 return CXCursor_ObjCInterfaceDecl;
3618 case Decl::ObjCIvar:
3619 return CXCursor_ObjCIvarDecl;
3620 case Decl::ObjCMethod:
3621 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3622 ? CXCursor_ObjCInstanceMethodDecl
3623 : CXCursor_ObjCClassMethodDecl;
3624 case Decl::CXXMethod:
3625 return CXCursor_CXXMethod;
3626 case Decl::CXXConstructor:
3627 return CXCursor_Constructor;
3628 case Decl::CXXDestructor:
3629 return CXCursor_Destructor;
3630 case Decl::CXXConversion:
3631 return CXCursor_ConversionFunction;
3632 case Decl::ObjCProperty:
3633 return CXCursor_ObjCPropertyDecl;
3634 case Decl::ObjCProtocol:
3635 return CXCursor_ObjCProtocolDecl;
3636 case Decl::ParmVar:
3637 return CXCursor_ParmDecl;
3638 case Decl::Typedef:
3639 return CXCursor_TypedefDecl;
3640 case Decl::TypeAlias:
3641 return CXCursor_TypeAliasDecl;
3642 case Decl::TypeAliasTemplate:
3643 return CXCursor_TypeAliasTemplateDecl;
3644 case Decl::Var:
3645 return CXCursor_VarDecl;
3646 case Decl::Namespace:
3647 return CXCursor_Namespace;
3648 case Decl::NamespaceAlias:
3649 return CXCursor_NamespaceAlias;
3650 case Decl::TemplateTypeParm:
3651 return CXCursor_TemplateTypeParameter;
3652 case Decl::NonTypeTemplateParm:
3653 return CXCursor_NonTypeTemplateParameter;
3654 case Decl::TemplateTemplateParm:
3655 return CXCursor_TemplateTemplateParameter;
3656 case Decl::FunctionTemplate:
3657 return CXCursor_FunctionTemplate;
3658 case Decl::ClassTemplate:
3659 return CXCursor_ClassTemplate;
3660 case Decl::AccessSpec:
3661 return CXCursor_CXXAccessSpecifier;
3662 case Decl::ClassTemplatePartialSpecialization:
3663 return CXCursor_ClassTemplatePartialSpecialization;
3664 case Decl::UsingDirective:
3665 return CXCursor_UsingDirective;
3666 case Decl::StaticAssert:
3667 return CXCursor_StaticAssert;
3668 case Decl::Friend:
3669 return CXCursor_FriendDecl;
3670 case Decl::TranslationUnit:
3671 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003672
Fangrui Song050229d2018-11-24 00:14:31 +00003673 case Decl::Using:
3674 case Decl::UnresolvedUsingValue:
3675 case Decl::UnresolvedUsingTypename:
3676 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003677
Fangrui Song050229d2018-11-24 00:14:31 +00003678 case Decl::ObjCPropertyImpl:
3679 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3680 case ObjCPropertyImplDecl::Dynamic:
3681 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003682
Fangrui Song050229d2018-11-24 00:14:31 +00003683 case ObjCPropertyImplDecl::Synthesize:
3684 return CXCursor_ObjCSynthesizeDecl;
3685 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003686 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003687
3688 case Decl::Import:
3689 return CXCursor_ModuleImportDecl;
3690
3691 case Decl::ObjCTypeParam:
3692 return CXCursor_TemplateTypeParameter;
3693
3694 default:
3695 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3696 switch (TD->getTagKind()) {
3697 case TTK_Interface: // fall through
3698 case TTK_Struct:
3699 return CXCursor_StructDecl;
3700 case TTK_Class:
3701 return CXCursor_ClassDecl;
3702 case TTK_Union:
3703 return CXCursor_UnionDecl;
3704 case TTK_Enum:
3705 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003706 }
Fangrui Song050229d2018-11-24 00:14:31 +00003707 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003708 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003709
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003710 return CXCursor_UnexposedDecl;
3711}
3712
Douglas Gregor55b037b2010-07-08 20:55:51 +00003713static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003714 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003715 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003716 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003717
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003718 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003719
Eric Liu88de9f62018-09-19 09:34:55 +00003720 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3721 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003722 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003723 auto MD = PP.getMacroDefinition(M->first);
3724 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003725 MacroInfo *MI = MD.getMacroInfo();
3726 if (MI && MI->isUsedForHeaderGuard())
3727 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003728
Eric Liud485df12018-09-05 14:59:17 +00003729 Results.AddResult(
3730 Result(M->first, MI,
3731 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3732 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003733 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003734 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003735
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003736 Results.ExitScope();
3737}
3738
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003739static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003740 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003741 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003742
Douglas Gregorce0e8562010-08-23 21:54:33 +00003743 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003744
Douglas Gregorce0e8562010-08-23 21:54:33 +00003745 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3746 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003747 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003748 Results.AddResult(Result("__func__", CCP_Constant));
3749 Results.ExitScope();
3750}
3751
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003752static void HandleCodeCompleteResults(Sema *S,
3753 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003754 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003755 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003756 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003757 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003758 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003759}
3760
Ilya Biryukov41109672018-12-13 15:36:32 +00003761static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003762mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003763 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003764 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003765 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003766
John McCallfaf5fb42010-08-26 23:41:50 +00003767 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003768 return CodeCompletionContext::CCC_ClassStructUnion;
3769
John McCallfaf5fb42010-08-26 23:41:50 +00003770 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003771 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003772
John McCallfaf5fb42010-08-26 23:41:50 +00003773 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003774 return CodeCompletionContext::CCC_ObjCImplementation;
3775
John McCallfaf5fb42010-08-26 23:41:50 +00003776 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003777 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003778
John McCallfaf5fb42010-08-26 23:41:50 +00003779 case Sema::PCC_Template:
3780 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003781 if (S.CurContext->isFileContext())
3782 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003783 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003784 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003785 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003786
John McCallfaf5fb42010-08-26 23:41:50 +00003787 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003788 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003789
John McCallfaf5fb42010-08-26 23:41:50 +00003790 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003791 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003792 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003793 return CodeCompletionContext::CCC_ParenthesizedExpression;
3794 else
3795 return CodeCompletionContext::CCC_Expression;
3796
3797 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003798 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003799 case Sema::PCC_Condition:
3800 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3801 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003802
John McCallfaf5fb42010-08-26 23:41:50 +00003803 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003804 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003805
John McCallfaf5fb42010-08-26 23:41:50 +00003806 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003807 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003808
3809 case Sema::PCC_ParenthesizedExpression:
3810 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003811
Douglas Gregor80039242011-02-15 20:33:25 +00003812 case Sema::PCC_LocalDeclarationSpecifiers:
3813 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003814 }
David Blaikie8a40f702012-01-17 06:56:22 +00003815
3816 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003817}
3818
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003819/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003820/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003821/// overridden function as well as adding new functionality.
3822///
3823/// \param S The semantic analysis object for which we are generating results.
3824///
3825/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003826/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003827static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3828 ResultBuilder &Results) {
3829 // Look through blocks.
3830 DeclContext *CurContext = S.CurContext;
3831 while (isa<BlockDecl>(CurContext))
3832 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003833
Douglas Gregorac322ec2010-08-27 21:18:54 +00003834 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3835 if (!Method || !Method->isVirtual())
3836 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003837
3838 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003839 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003840 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003841 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003842 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003843
Douglas Gregor75acd922011-09-27 23:30:47 +00003844 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003845 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003846 CodeCompletionBuilder Builder(Results.getAllocator(),
3847 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003848 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3849 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003850
Douglas Gregorac322ec2010-08-27 21:18:54 +00003851 // If we need a nested-name-specifier, add one now.
3852 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003853 NestedNameSpecifier *NNS = getRequiredQualification(
3854 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003855 if (NNS) {
3856 std::string Str;
3857 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003858 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003859 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003860 }
3861 } else if (!InContext->Equals(Overridden->getDeclContext()))
3862 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003863
Fangrui Song050229d2018-11-24 00:14:31 +00003864 Builder.AddTypedTextChunk(
3865 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003866 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003867 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003868 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003869 if (FirstParam)
3870 FirstParam = false;
3871 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003872 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003873
Aaron Ballman43b68be2014-03-07 17:50:17 +00003874 Builder.AddPlaceholderChunk(
3875 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003876 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003877 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003878 Results.AddResult(CodeCompletionResult(
3879 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3880 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003881 Results.Ignore(Overridden);
3882 }
3883}
3884
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003885void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003886 ModuleIdPath Path) {
3887 typedef CodeCompletionResult Result;
3888 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003889 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003890 CodeCompletionContext::CCC_Other);
3891 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003892
Douglas Gregor07f43572012-01-29 18:15:03 +00003893 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003894 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003895 typedef CodeCompletionResult Result;
3896 if (Path.empty()) {
3897 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003898 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003899 PP.getHeaderSearchInfo().collectAllModules(Modules);
3900 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3901 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003902 Builder.getAllocator().CopyString(Modules[I]->Name));
3903 Results.AddResult(Result(
3904 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3905 Modules[I]->isAvailable() ? CXAvailability_Available
3906 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003907 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003908 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003909 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003910 Module *Mod =
3911 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3912 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003913 // Enumerate submodules.
3914 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003915 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003916 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003917 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003918
Douglas Gregor07f43572012-01-29 18:15:03 +00003919 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003920 Builder.getAllocator().CopyString((*Sub)->Name));
3921 Results.AddResult(Result(
3922 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3923 (*Sub)->isAvailable() ? CXAvailability_Available
3924 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003925 }
3926 }
3927 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003928 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003929 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003930 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003931}
3932
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003933void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003934 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003935 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003936 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003937 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003938 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003939
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003940 // Determine how to filter results, e.g., so that the names of
3941 // values (functions, enumerators, function templates, etc.) are
3942 // only allowed where we can have an expression.
3943 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003944 case PCC_Namespace:
3945 case PCC_Class:
3946 case PCC_ObjCInterface:
3947 case PCC_ObjCImplementation:
3948 case PCC_ObjCInstanceVariableList:
3949 case PCC_Template:
3950 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003951 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003952 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003953 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3954 break;
3955
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003956 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003957 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003958 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003959 case PCC_ForInit:
3960 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003961 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003962 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3963 else
3964 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003965
David Blaikiebbafb8a2012-03-11 07:00:24 +00003966 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003967 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003968 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003969
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003970 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003971 // Unfiltered
3972 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003973 }
3974
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003975 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003976 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00003977 auto ThisType = getCurrentThisType();
3978 if (!ThisType.isNull())
3979 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003980
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003981 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003982 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003983 CodeCompleter->includeGlobals(),
3984 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003985
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003986 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003987 Results.ExitScope();
3988
Douglas Gregorce0e8562010-08-23 21:54:33 +00003989 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003990 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003991 case PCC_Expression:
3992 case PCC_Statement:
3993 case PCC_RecoveryInFunction:
3994 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003995 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003996 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003997
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003998 case PCC_Namespace:
3999 case PCC_Class:
4000 case PCC_ObjCInterface:
4001 case PCC_ObjCImplementation:
4002 case PCC_ObjCInstanceVariableList:
4003 case PCC_Template:
4004 case PCC_MemberTemplate:
4005 case PCC_ForInit:
4006 case PCC_Condition:
4007 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004008 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004009 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00004010 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004011
Douglas Gregor9eb77012009-11-07 00:00:49 +00004012 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004013 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004014
Douglas Gregor50832e02010-09-20 22:39:41 +00004015 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004016 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00004017}
4018
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004019static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004020 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004021 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00004022 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004023 ResultBuilder &Results);
4024
4025void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
4026 bool AllowNonIdentifiers,
4027 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00004028 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004029 ResultBuilder Results(
4030 *this, CodeCompleter->getAllocator(),
4031 CodeCompleter->getCodeCompletionTUInfo(),
4032 AllowNestedNameSpecifiers
4033 // FIXME: Try to separate codepath leading here to deduce whether we
4034 // need an existing symbol or a new one.
4035 ? CodeCompletionContext::CCC_SymbolOrNewName
4036 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004037 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004038
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004039 // Type qualifiers can come after names.
4040 Results.AddResult(Result("const"));
4041 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004042 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004043 Results.AddResult(Result("restrict"));
4044
David Blaikiebbafb8a2012-03-11 07:00:24 +00004045 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004046 if (getLangOpts().CPlusPlus11 &&
4047 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4048 DS.getTypeSpecType() == DeclSpec::TST_struct))
4049 Results.AddResult("final");
4050
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004051 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004052 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004053 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004054
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004055 // Add nested-name-specifiers.
4056 if (AllowNestedNameSpecifiers) {
4057 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004058 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004059 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4060 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004061 CodeCompleter->includeGlobals(),
4062 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004063 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004064 }
4065 }
4066 Results.ExitScope();
4067
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004068 // If we're in a context where we might have an expression (rather than a
4069 // declaration), and what we've seen so far is an Objective-C type that could
4070 // be a receiver of a class message, this may be a class message send with
4071 // the initial opening bracket '[' missing. Add appropriate completions.
4072 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004073 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004074 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004075 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4076 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004077 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004078 (S->getFlags() & Scope::DeclScope) != 0 &&
4079 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004080 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4081 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004082 ParsedType T = DS.getRepAsType();
4083 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004084 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004085 }
4086
Douglas Gregor56ccce02010-08-24 04:59:56 +00004087 // Note that we intentionally suppress macro results here, since we do not
4088 // encourage using macros to produce the names of entities.
4089
Fangrui Song050229d2018-11-24 00:14:31 +00004090 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004091 Results.data(), Results.size());
4092}
4093
Douglas Gregor68762e72010-08-23 21:17:50 +00004094struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004095 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4096 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004097 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004098 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004099
Douglas Gregor68762e72010-08-23 21:17:50 +00004100 QualType PreferredType;
4101 bool IntegralConstantExpression;
4102 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004103 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004104 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004105};
4106
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004107namespace {
4108/// Information that allows to avoid completing redundant enumerators.
4109struct CoveredEnumerators {
4110 llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
4111 NestedNameSpecifier *SuggestedQualifier = nullptr;
4112};
4113} // namespace
4114
4115static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
4116 EnumDecl *Enum, DeclContext *CurContext,
4117 const CoveredEnumerators &Enumerators) {
4118 NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
4119 if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
4120 // If there are no prior enumerators in C++, check whether we have to
4121 // qualify the names of the enumerators that we suggest, because they
4122 // may not be visible in this scope.
4123 Qualifier = getRequiredQualification(Context, CurContext, Enum);
4124 }
4125
4126 Results.EnterNewScope();
4127 for (auto *E : Enum->enumerators()) {
4128 if (Enumerators.Seen.count(E))
4129 continue;
4130
4131 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
4132 Results.AddResult(R, CurContext, nullptr, false);
4133 }
4134 Results.ExitScope();
4135}
4136
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004137/// Try to find a corresponding FunctionProtoType for function-like types (e.g.
4138/// function pointers, std::function, etc).
4139static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) {
4140 assert(!T.isNull());
4141 // Try to extract first template argument from std::function<> and similar.
4142 // Note we only handle the sugared types, they closely match what users wrote.
4143 // We explicitly choose to not handle ClassTemplateSpecializationDecl.
4144 if (auto *Specialization = T->getAs<TemplateSpecializationType>()) {
4145 if (Specialization->getNumArgs() != 1)
4146 return nullptr;
4147 const TemplateArgument &Argument = Specialization->getArg(0);
4148 if (Argument.getKind() != TemplateArgument::Type)
4149 return nullptr;
4150 return Argument.getAsType()->getAs<FunctionProtoType>();
4151 }
4152 // Handle other cases.
4153 if (T->isPointerType())
4154 T = T->getPointeeType();
4155 return T->getAs<FunctionProtoType>();
4156}
4157
4158/// Adds a pattern completion for a lambda expression with the specified
4159/// parameter types and placeholders for parameter names.
4160static void AddLambdaCompletion(ResultBuilder &Results,
4161 llvm::ArrayRef<QualType> Parameters,
4162 const LangOptions &LangOpts) {
Ilya Biryukovfd11a5f2019-05-23 16:39:26 +00004163 if (!Results.includeCodePatterns())
4164 return;
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004165 CodeCompletionBuilder Completion(Results.getAllocator(),
4166 Results.getCodeCompletionTUInfo());
4167 // [](<parameters>) {}
4168 Completion.AddChunk(CodeCompletionString::CK_LeftBracket);
4169 Completion.AddPlaceholderChunk("=");
4170 Completion.AddChunk(CodeCompletionString::CK_RightBracket);
4171 if (!Parameters.empty()) {
4172 Completion.AddChunk(CodeCompletionString::CK_LeftParen);
4173 bool First = true;
4174 for (auto Parameter : Parameters) {
4175 if (!First)
4176 Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma);
4177 else
4178 First = false;
4179
4180 constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!";
4181 std::string Type = NamePlaceholder;
4182 Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts));
4183 llvm::StringRef Prefix, Suffix;
4184 std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder);
4185 Prefix = Prefix.rtrim();
4186 Suffix = Suffix.ltrim();
4187
4188 Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix));
4189 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4190 Completion.AddPlaceholderChunk("parameter");
4191 Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix));
4192 };
4193 Completion.AddChunk(CodeCompletionString::CK_RightParen);
4194 }
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004195 Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004196 Completion.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004197 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004198 Completion.AddPlaceholderChunk("body");
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004199 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004200 Completion.AddChunk(CodeCompletionString::CK_RightBrace);
4201
4202 Results.AddResult(Completion.TakeString());
4203}
4204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004205/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004206/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004207void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004208 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004209 ResultBuilder Results(
4210 *this, CodeCompleter->getAllocator(),
4211 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004212 CodeCompletionContext(
4213 Data.IsParenthesized
4214 ? CodeCompletionContext::CCC_ParenthesizedExpression
4215 : CodeCompletionContext::CCC_Expression,
4216 Data.PreferredType));
4217 auto PCC =
4218 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004219 if (Data.ObjCCollection)
4220 Results.setFilter(&ResultBuilder::IsObjCCollection);
4221 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004222 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004223 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004224 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4225 else
4226 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004227
4228 if (!Data.PreferredType.isNull())
4229 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004230
Douglas Gregor68762e72010-08-23 21:17:50 +00004231 // Ignore any declarations that we were told that we don't care about.
4232 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4233 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004234
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004235 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004236 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004237 CodeCompleter->includeGlobals(),
4238 CodeCompleter->loadExternal());
4239
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004240 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004241 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004242 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004243
Douglas Gregor55b037b2010-07-08 20:55:51 +00004244 bool PreferredTypeIsPointer = false;
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004245 if (!Data.PreferredType.isNull()) {
Fangrui Song050229d2018-11-24 00:14:31 +00004246 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4247 Data.PreferredType->isMemberPointerType() ||
4248 Data.PreferredType->isBlockPointerType();
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004249 if (Data.PreferredType->isEnumeralType()) {
4250 EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();
4251 if (auto *Def = Enum->getDefinition())
4252 Enum = Def;
4253 // FIXME: collect covered enumerators in cases like:
4254 // if (x == my_enum::one) { ... } else if (x == ^) {}
4255 AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators());
4256 }
4257 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004258
Fangrui Song050229d2018-11-24 00:14:31 +00004259 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004260 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004261 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004262
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004263 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004264 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4265 PreferredTypeIsPointer);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004266
4267 // Complete a lambda expression when preferred type is a function.
4268 if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) {
4269 if (const FunctionProtoType *F =
4270 TryDeconstructFunctionLike(Data.PreferredType))
4271 AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts());
4272 }
4273
Eric Liuf5ba09f2018-07-04 10:01:18 +00004274 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4275 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004276}
4277
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004278void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4279 bool IsParenthesized) {
4280 return CodeCompleteExpression(
4281 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004282}
4283
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004284void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4285 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004286 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004287 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004288 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004289 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004290}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004291
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004292/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004293/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004294typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004295
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004296/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004297static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4298 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4299 if (Interface->hasDefinition())
4300 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004301
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004302 return Interface;
4303 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004304
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004305 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4306 if (Protocol->hasDefinition())
4307 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004308
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004309 return Protocol;
4310 }
4311 return Container;
4312}
4313
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004314/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004315/// declaration \p BD.
4316static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4317 CodeCompletionBuilder &Builder,
4318 const NamedDecl *BD,
4319 const FunctionTypeLoc &BlockLoc,
4320 const FunctionProtoTypeLoc &BlockProtoLoc) {
4321 Builder.AddResultTypeChunk(
4322 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4323 Policy, Builder.getAllocator()));
4324
4325 AddTypedNameChunk(Context, Policy, BD, Builder);
4326 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4327
4328 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4329 Builder.AddPlaceholderChunk("...");
4330 } else {
4331 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4332 if (I)
4333 Builder.AddChunk(CodeCompletionString::CK_Comma);
4334
4335 // Format the placeholder string.
4336 std::string PlaceholderStr =
4337 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4338
4339 if (I == N - 1 && BlockProtoLoc &&
4340 BlockProtoLoc.getTypePtr()->isVariadic())
4341 PlaceholderStr += ", ...";
4342
4343 // Add the placeholder string.
4344 Builder.AddPlaceholderChunk(
4345 Builder.getAllocator().CopyString(PlaceholderStr));
4346 }
4347 }
4348
4349 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4350}
4351
Fangrui Song050229d2018-11-24 00:14:31 +00004352static void
4353AddObjCProperties(const CodeCompletionContext &CCContext,
4354 ObjCContainerDecl *Container, bool AllowCategories,
4355 bool AllowNullaryMethods, DeclContext *CurContext,
4356 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4357 bool IsBaseExprStatement = false,
4358 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004359 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004360
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004361 // Retrieve the definition.
4362 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004363
Douglas Gregor9291bad2009-11-18 01:29:26 +00004364 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004365 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004366 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004367 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004368
Alex Lorenzbaef8022016-11-09 13:43:18 +00004369 // FIXME: Provide block invocation completion for non-statement
4370 // expressions.
4371 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4372 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004373 Result R = Result(P, Results.getBasePriority(P), nullptr);
4374 if (!InOriginalClass)
4375 setInBaseClass(R);
4376 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004377 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004378 }
4379
4380 // Block setter and invocation completion is provided only when we are able
4381 // to find the FunctionProtoTypeLoc with parameter names for the block.
4382 FunctionTypeLoc BlockLoc;
4383 FunctionProtoTypeLoc BlockProtoLoc;
4384 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4385 BlockProtoLoc);
4386 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004387 Result R = Result(P, Results.getBasePriority(P), nullptr);
4388 if (!InOriginalClass)
4389 setInBaseClass(R);
4390 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004391 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004392 }
4393
4394 // The default completion result for block properties should be the block
4395 // invocation completion when the base expression is a statement.
4396 CodeCompletionBuilder Builder(Results.getAllocator(),
4397 Results.getCodeCompletionTUInfo());
4398 AddObjCBlockCall(Container->getASTContext(),
4399 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4400 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004401 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4402 if (!InOriginalClass)
4403 setInBaseClass(R);
4404 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004405
4406 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004407 // statement and the block property is mutable.
4408 if (!P->isReadOnly()) {
4409 CodeCompletionBuilder Builder(Results.getAllocator(),
4410 Results.getCodeCompletionTUInfo());
4411 AddResultTypeChunk(Container->getASTContext(),
4412 getCompletionPrintingPolicy(Results.getSema()), P,
4413 CCContext.getBaseType(), Builder);
4414 Builder.AddTypedTextChunk(
4415 Results.getAllocator().CopyString(P->getName()));
4416 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004417
Alex Lorenzbaef8022016-11-09 13:43:18 +00004418 std::string PlaceholderStr = formatBlockPlaceholder(
4419 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4420 BlockProtoLoc, /*SuppressBlockName=*/true);
4421 // Add the placeholder string.
4422 Builder.AddPlaceholderChunk(
4423 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004424
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004425 // When completing blocks properties that return void the default
4426 // property completion result should show up before the setter,
4427 // otherwise the setter completion should show up before the default
4428 // property completion, as we normally want to use the result of the
4429 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004430 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004431 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004432 Results.getBasePriority(P) +
4433 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4434 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004435 : -CCD_BlockPropertySetter));
4436 if (!InOriginalClass)
4437 setInBaseClass(R);
4438 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004439 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004440 };
4441
4442 if (IsClassProperty) {
4443 for (const auto *P : Container->class_properties())
4444 AddProperty(P);
4445 } else {
4446 for (const auto *P : Container->instance_properties())
4447 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004448 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004449
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004450 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004451 if (AllowNullaryMethods) {
4452 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004453 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004454 // Adds a method result
4455 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4456 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4457 if (!Name)
4458 return;
4459 if (!AddedProperties.insert(Name).second)
4460 return;
4461 CodeCompletionBuilder Builder(Results.getAllocator(),
4462 Results.getCodeCompletionTUInfo());
4463 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4464 Builder.AddTypedTextChunk(
4465 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004466 Result R = Result(Builder.TakeString(), M,
4467 CCP_MemberDeclaration + CCD_MethodAsProperty);
4468 if (!InOriginalClass)
4469 setInBaseClass(R);
4470 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004471 };
4472
4473 if (IsClassProperty) {
4474 for (const auto *M : Container->methods()) {
4475 // Gather the class method that can be used as implicit property
4476 // getters. Methods with arguments or methods that return void aren't
4477 // added to the results as they can't be used as a getter.
4478 if (!M->getSelector().isUnarySelector() ||
4479 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4480 continue;
4481 AddMethod(M);
4482 }
4483 } else {
4484 for (auto *M : Container->methods()) {
4485 if (M->getSelector().isUnarySelector())
4486 AddMethod(M);
4487 }
Douglas Gregor95147142011-05-05 15:50:42 +00004488 }
4489 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004490
Douglas Gregor9291bad2009-11-18 01:29:26 +00004491 // Add properties in referenced protocols.
4492 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004493 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004494 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004495 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004496 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004497 /*InOriginalClass*/ false);
4498 } else if (ObjCInterfaceDecl *IFace =
4499 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004500 if (AllowCategories) {
4501 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004502 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004503 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004504 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004505 IsBaseExprStatement, IsClassProperty,
4506 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004507 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004508
Douglas Gregor9291bad2009-11-18 01:29:26 +00004509 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004510 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004511 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004512 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004513 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004514 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004515
Douglas Gregor9291bad2009-11-18 01:29:26 +00004516 // Look in the superclass.
4517 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004518 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004519 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004520 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004521 /*InOriginalClass*/ false);
4522 } else if (const auto *Category =
4523 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004524 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004525 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004526 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004527 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004528 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004529 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004530 }
4531}
4532
Fangrui Song050229d2018-11-24 00:14:31 +00004533static void
4534AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
4535 Scope *S, QualType BaseType, RecordDecl *RD,
4536 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004537 // Indicate that we are performing a member access, and the cv-qualifiers
4538 // for the base object type.
4539 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4540
4541 // Access to a C/C++ class, struct, or union.
4542 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004543 std::vector<FixItHint> FixIts;
4544 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004545 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004546 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004547 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004548 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004549 /*IncludeDependentBases=*/true,
4550 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004551
4552 if (SemaRef.getLangOpts().CPlusPlus) {
4553 if (!Results.empty()) {
4554 // The "template" keyword can follow "->" or "." in the grammar.
4555 // However, we only want to suggest the template keyword if something
4556 // is dependent.
4557 bool IsDependent = BaseType->isDependentType();
4558 if (!IsDependent) {
4559 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4560 if (DeclContext *Ctx = DepScope->getEntity()) {
4561 IsDependent = Ctx->isDependentContext();
4562 break;
4563 }
4564 }
4565
4566 if (IsDependent)
4567 Results.AddResult(CodeCompletionResult("template"));
4568 }
4569 }
4570}
4571
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004572void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004573 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004574 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004575 bool IsBaseExprStatement,
4576 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004577 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004578 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004579
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004580 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4581 if (ConvertedBase.isInvalid())
4582 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004583 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4584
4585 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004586
4587 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004588 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004589 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004590 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004591
Douglas Gregor21325842011-07-07 16:03:39 +00004592 if (IsArrow) {
4593 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004594 } else {
4595 if (ConvertedBaseType->isObjCObjectPointerType() ||
4596 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004597 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004598 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004599 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4600 }
4601 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004602
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004603 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004604 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004605 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004606 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004607 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004608
Fangrui Song050229d2018-11-24 00:14:31 +00004609 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4610 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004611 if (!Base)
4612 return false;
4613
4614 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4615 if (ConvertedBase.isInvalid())
4616 return false;
4617 Base = ConvertedBase.get();
4618
4619 QualType BaseType = Base->getType();
4620
4621 if (IsArrow) {
4622 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4623 BaseType = Ptr->getPointeeType();
4624 else if (BaseType->isObjCObjectPointerType())
4625 /*Do nothing*/;
4626 else
4627 return false;
4628 }
4629
4630 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4631 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4632 Record->getDecl(),
4633 std::move(AccessOpFixIt));
4634 } else if (const auto *TST =
4635 BaseType->getAs<TemplateSpecializationType>()) {
4636 TemplateName TN = TST->getTemplateName();
4637 if (const auto *TD =
4638 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4639 CXXRecordDecl *RD = TD->getTemplatedDecl();
4640 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4641 std::move(AccessOpFixIt));
4642 }
4643 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4644 if (auto *RD = ICNT->getDecl())
4645 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4646 std::move(AccessOpFixIt));
4647 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4648 // Objective-C property reference.
4649 AddedPropertiesSet AddedProperties;
4650
4651 if (const ObjCObjectPointerType *ObjCPtr =
4652 BaseType->getAsObjCInterfacePointerType()) {
4653 // Add property results based on our interface.
4654 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4655 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4656 /*AllowNullaryMethods=*/true, CurContext,
4657 AddedProperties, Results, IsBaseExprStatement);
4658 }
4659
4660 // Add properties from the protocols in a qualified interface.
4661 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4662 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4663 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004664 IsBaseExprStatement, /*IsClassProperty*/ false,
4665 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004666 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4667 (!IsArrow && BaseType->isObjCObjectType())) {
4668 // Objective-C instance variable access.
4669 ObjCInterfaceDecl *Class = nullptr;
4670 if (const ObjCObjectPointerType *ObjCPtr =
4671 BaseType->getAs<ObjCObjectPointerType>())
4672 Class = ObjCPtr->getInterfaceDecl();
4673 else
4674 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4675
4676 // Add all ivars from this class and its superclasses.
4677 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004678 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004679 Results.setFilter(&ResultBuilder::IsObjCIvar);
4680 LookupVisibleDecls(
4681 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4682 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4683 }
4684 }
4685
4686 // FIXME: How do we cope with isa?
4687 return true;
4688 };
4689
Douglas Gregor9291bad2009-11-18 01:29:26 +00004690 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004691
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004692 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4693 if (CodeCompleter->includeFixIts()) {
4694 const CharSourceRange OpRange =
4695 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4696 CompletionSucceded |= DoCompletion(
4697 OtherOpBase, !IsArrow,
4698 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004699 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004700
Douglas Gregor9291bad2009-11-18 01:29:26 +00004701 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004702
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004703 if (!CompletionSucceded)
4704 return;
4705
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004706 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004707 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4708 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004709}
4710
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004711void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4712 IdentifierInfo &ClassName,
4713 SourceLocation ClassNameLoc,
4714 bool IsBaseExprStatement) {
4715 IdentifierInfo *ClassNamePtr = &ClassName;
4716 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4717 if (!IFace)
4718 return;
4719 CodeCompletionContext CCContext(
4720 CodeCompletionContext::CCC_ObjCPropertyAccess);
4721 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4722 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4723 &ResultBuilder::IsMember);
4724 Results.EnterNewScope();
4725 AddedPropertiesSet AddedProperties;
4726 AddObjCProperties(CCContext, IFace, true,
4727 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4728 Results, IsBaseExprStatement,
4729 /*IsClassProperty=*/true);
4730 Results.ExitScope();
4731 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4732 Results.data(), Results.size());
4733}
4734
Faisal Vali090da2d2018-01-01 18:23:28 +00004735void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004736 if (!CodeCompleter)
4737 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004738
4739 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004740 enum CodeCompletionContext::Kind ContextKind =
4741 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004742 switch ((DeclSpec::TST)TagSpec) {
4743 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004744 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004745 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004746 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004747
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004748 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004749 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004750 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004751 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004752
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004753 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004754 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004755 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004756 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004757 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004758 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004759
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004760 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004761 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004762 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004763
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004764 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4765 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004766 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004767
4768 // First pass: look for tags.
4769 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004770 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004771 CodeCompleter->includeGlobals(),
4772 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004773
Douglas Gregor39982192010-08-15 06:18:01 +00004774 if (CodeCompleter->includeGlobals()) {
4775 // Second pass: look for nested name specifiers.
4776 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004777 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4778 CodeCompleter->includeGlobals(),
4779 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004780 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004781
Douglas Gregor0ac41382010-09-23 23:01:17 +00004782 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004783 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004784}
4785
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004786static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4787 const LangOptions &LangOpts) {
4788 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4789 Results.AddResult("const");
4790 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4791 Results.AddResult("volatile");
4792 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4793 Results.AddResult("restrict");
4794 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4795 Results.AddResult("_Atomic");
4796 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4797 Results.AddResult("__unaligned");
4798}
4799
Douglas Gregor28c78432010-08-27 17:35:51 +00004800void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004801 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004802 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004803 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004804 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004805 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004806 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004807 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004808 Results.data(), Results.size());
4809}
4810
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004811void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4812 const VirtSpecifiers *VS) {
4813 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4814 CodeCompleter->getCodeCompletionTUInfo(),
4815 CodeCompletionContext::CCC_TypeQualifiers);
4816 Results.EnterNewScope();
4817 AddTypeQualifierResults(DS, Results, LangOpts);
4818 if (LangOpts.CPlusPlus11) {
4819 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004820 if (D.getContext() == DeclaratorContext::MemberContext &&
4821 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004822 if (!VS || !VS->isFinalSpecified())
4823 Results.AddResult("final");
4824 if (!VS || !VS->isOverrideSpecified())
4825 Results.AddResult("override");
4826 }
4827 }
4828 Results.ExitScope();
4829 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4830 Results.data(), Results.size());
4831}
4832
Benjamin Kramer72dae622016-02-18 15:30:24 +00004833void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4834 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4835}
4836
Douglas Gregord328d572009-09-21 18:10:23 +00004837void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004838 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004839 return;
John McCall5939b162011-08-06 07:30:58 +00004840
Richard Smithef6c43d2018-07-26 18:41:30 +00004841 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004842 // Condition expression might be invalid, do not continue in this case.
4843 if (!Switch->getCond())
4844 return;
John McCall5939b162011-08-06 07:30:58 +00004845 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4846 if (!type->isEnumeralType()) {
4847 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004848 Data.IntegralConstantExpression = true;
4849 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004850 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004851 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004852
Douglas Gregord328d572009-09-21 18:10:23 +00004853 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004854 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004855 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004856 if (EnumDecl *Def = Enum->getDefinition())
4857 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004858
Douglas Gregord328d572009-09-21 18:10:23 +00004859 // Determine which enumerators we have already seen in the switch statement.
4860 // FIXME: Ideally, we would also be able to look *past* the code-completion
4861 // token, in case we are code-completing in the middle of the switch and not
4862 // at the end. However, we aren't able to do so at the moment.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004863 CoveredEnumerators Enumerators;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004864 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004865 SC = SC->getNextSwitchCase()) {
4866 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4867 if (!Case)
4868 continue;
4869
4870 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004871 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4872 if (auto *Enumerator =
4873 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004874 // We look into the AST of the case statement to determine which
4875 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004876 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004877 // values of each enumerator. However, value-based approach would not
4878 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004879 // template are type- and value-dependent.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004880 Enumerators.Seen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004881
Douglas Gregorf2510672009-09-21 19:57:38 +00004882 // If this is a qualified-id, keep track of the nested-name-specifier
4883 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004884 //
4885 // switch (TagD.getKind()) {
4886 // case TagDecl::TK_enum:
4887 // break;
4888 // case XXX
4889 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004890 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004891 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4892 // TK_struct, and TK_class.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004893 Enumerators.SuggestedQualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004894 }
4895 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004896
Douglas Gregord328d572009-09-21 18:10:23 +00004897 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004898 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004899 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004900 CodeCompletionContext::CCC_Expression);
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004901 AddEnumerators(Results, Context, Enum, CurContext, Enumerators);
Douglas Gregor285560922010-04-06 20:02:15 +00004902
Douglas Gregor21325842011-07-07 16:03:39 +00004903 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004904 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004905 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004906 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4907 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004908}
4909
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004910static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004911 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004912 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004913
4914 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004915 if (!Args[I])
4916 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004917
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004918 return false;
4919}
4920
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004921typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4922
Fangrui Song050229d2018-11-24 00:14:31 +00004923static void mergeCandidatesWithResults(
4924 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
4925 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Fangrui Song899d1392019-04-24 14:43:05 +00004926 // Sort the overload candidate set by placing the best overloads first.
4927 llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
4928 const OverloadCandidate &Y) {
4929 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4930 CandidateSet.getKind());
4931 });
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004932
Fangrui Song899d1392019-04-24 14:43:05 +00004933 // Add the remaining viable overload candidates as code-completion results.
4934 for (OverloadCandidate &Candidate : CandidateSet) {
4935 if (Candidate.Function && Candidate.Function->isDeleted())
4936 continue;
4937 if (Candidate.Viable)
4938 Results.push_back(ResultCandidate(Candidate.Function));
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004939 }
4940}
4941
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004942/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004943/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004944static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00004945 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004946
4947 // Given the overloads 'Candidates' for a function call matching all arguments
4948 // up to N, return the type of the Nth parameter if it is the same for all
4949 // overload candidates.
4950 QualType ParamType;
4951 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00004952 if (const auto *FType = Candidate.getFunctionType())
4953 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004954 if (N < Proto->getNumParams()) {
4955 if (ParamType.isNull())
4956 ParamType = Proto->getParamType(N);
4957 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00004958 ParamType.getNonReferenceType(),
4959 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004960 // Otherwise return a default-constructed QualType.
4961 return QualType();
4962 }
4963 }
4964
4965 return ParamType;
4966}
4967
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004968static QualType
4969ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4970 MutableArrayRef<ResultCandidate> Candidates,
4971 unsigned CurrentArg, SourceLocation OpenParLoc) {
4972 if (Candidates.empty())
4973 return QualType();
4974 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4975 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4976 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004977}
4978
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004979QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4980 ArrayRef<Expr *> Args,
4981 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004982 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004983 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004984
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004985 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004986 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004987 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4988 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004989 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004990 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004991
John McCall57500772009-12-16 12:17:52 +00004992 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004993 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004994 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004995
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004996 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004997
John McCall57500772009-12-16 12:17:52 +00004998 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004999 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005000 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005001 /*PartialOverloading=*/true);
5002 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
5003 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
5004 if (UME->hasExplicitTemplateArgs()) {
5005 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
5006 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00005007 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00005008
5009 // Add the base as first argument (use a nullptr if the base is implicit).
5010 SmallVector<Expr *, 12> ArgExprs(
5011 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005012 ArgExprs.append(Args.begin(), Args.end());
5013 UnresolvedSet<8> Decls;
5014 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00005015 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005016 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
5017 /*SuppressUsedConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00005018 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005019 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005020 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00005021 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005022 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00005023 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005024 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005025 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00005026 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005027 !FD->getType()->getAs<FunctionProtoType>())
5028 Results.push_back(ResultCandidate(FD));
5029 else
5030 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
5031 Args, CandidateSet,
5032 /*SuppressUsedConversions=*/false,
5033 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005034
5035 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
5036 // If expression's type is CXXRecordDecl, it may overload the function
5037 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005038 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00005039 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00005040 DeclarationName OpName =
5041 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005042 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
5043 LookupQualifiedName(R, DC);
5044 R.suppressDiagnostics();
5045 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
5046 ArgExprs.append(Args.begin(), Args.end());
5047 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
5048 /*ExplicitArgs=*/nullptr,
5049 /*SuppressUsedConversions=*/false,
5050 /*PartialOverloading=*/true);
5051 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005052 } else {
5053 // Lastly we check whether expression's type is function pointer or
5054 // function.
5055 QualType T = NakedFn->getType();
5056 if (!T->getPointeeType().isNull())
5057 T = T->getPointeeType();
5058
5059 if (auto FP = T->getAs<FunctionProtoType>()) {
5060 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00005061 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005062 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005063 Results.push_back(ResultCandidate(FP));
5064 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005065 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005066 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005067 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005068 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005069 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005070 QualType ParamType =
5071 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
5072 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005073}
5074
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005075QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
5076 SourceLocation Loc,
5077 ArrayRef<Expr *> Args,
5078 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005079 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005080 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005081
5082 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00005083 CXXRecordDecl *RD =
5084 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005085 if (!RD)
5086 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00005087
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005088 // FIXME: Provide support for member initializers.
5089 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005090
5091 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
5092
Fangrui Song050229d2018-11-24 00:14:31 +00005093 for (NamedDecl *C : LookupConstructors(RD)) {
5094 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
5095 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
5096 CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005097 /*SuppressUsedConversions=*/false,
Richard Smith76b90272019-05-09 03:59:21 +00005098 /*PartialOverloading=*/true,
5099 /*AllowExplicit*/ true);
Fangrui Song050229d2018-11-24 00:14:31 +00005100 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
5101 AddTemplateOverloadCandidate(
5102 FTD, DeclAccessPair::make(FTD, C->getAccess()),
5103 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
5104 /*SuppressUsedConversions=*/false,
Hans Wennborgd2b9fc82019-05-06 09:51:10 +00005105 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005106 }
5107 }
5108
5109 SmallVector<ResultCandidate, 8> Results;
5110 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005111 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00005112}
5113
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00005114QualType Sema::ProduceCtorInitMemberSignatureHelp(
5115 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
5116 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
5117 if (!CodeCompleter)
5118 return QualType();
5119
5120 CXXConstructorDecl *Constructor =
5121 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
5122 if (!Constructor)
5123 return QualType();
5124 // FIXME: Add support for Base class constructors as well.
5125 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
5126 Constructor->getParent(), SS, TemplateTypeTy, II))
5127 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
5128 MemberDecl->getLocation(), ArgExprs,
5129 OpenParLoc);
5130 return QualType();
5131}
5132
John McCall48871652010-08-21 09:40:31 +00005133void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
5134 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005135 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005136 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005137 return;
5138 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005139
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005140 CodeCompleteExpressionData Data;
5141 Data.PreferredType = VD->getType();
5142 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5143 Data.IgnoreDecls.push_back(VD);
5144
5145 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005146}
5147
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005148void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005149 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005150 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005151 mapCodeCompletionContext(*this, PCC_Statement));
5152 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5153 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005154
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005155 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5156 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005157 CodeCompleter->includeGlobals(),
5158 CodeCompleter->loadExternal());
5159
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005160 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005161
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005162 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005163 CodeCompletionBuilder Builder(Results.getAllocator(),
5164 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005165 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005166 if (Results.includeCodePatterns()) {
5167 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5168 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5169 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5170 Builder.AddPlaceholderChunk("statements");
5171 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5172 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5173 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005174 Results.AddResult(Builder.TakeString());
5175
5176 // "else if" block
5177 Builder.AddTypedTextChunk("else");
5178 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5179 Builder.AddTextChunk("if");
5180 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005182 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005183 Builder.AddPlaceholderChunk("condition");
5184 else
5185 Builder.AddPlaceholderChunk("expression");
5186 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005187 if (Results.includeCodePatterns()) {
5188 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5189 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5190 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5191 Builder.AddPlaceholderChunk("statements");
5192 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5193 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5194 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005195 Results.AddResult(Builder.TakeString());
5196
5197 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005198
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005199 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005200 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005201
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005202 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005203 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005204
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005205 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005206 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005207}
5208
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005209void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005210 bool EnteringContext, QualType BaseType) {
Eric Liu06d34022017-12-12 11:35:46 +00005211 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005212 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005213
Eric Liu06d34022017-12-12 11:35:46 +00005214 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5215 // "a::b::" is not corresponding to any context/namespace in the AST), since
5216 // it can be useful for global code completion which have information about
5217 // contexts/symbols that are not in the AST.
5218 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005219 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00005220 CC.setCXXScopeSpecifier(SS);
Eric Liu206740e2019-02-21 11:22:58 +00005221 // As SS is invalid, we try to collect accessible contexts from the current
5222 // scope with a dummy lookup so that the completion consumer can try to
5223 // guess what the specified scope is.
5224 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5225 CodeCompleter->getCodeCompletionTUInfo(), CC);
5226 if (S->getEntity()) {
5227 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5228 BaseType);
5229 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5230 /*IncludeGlobalScope=*/false,
5231 /*LoadExternal=*/false);
5232 }
5233 HandleCodeCompleteResults(this, CodeCompleter,
5234 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005235 return;
5236 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005237 // Always pretend to enter a context to ensure that a dependent type
5238 // resolves to a dependent record.
5239 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005240 if (!Ctx)
5241 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005242
5243 // Try to instantiate any non-dependent declaration contexts before
5244 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005245 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005246 return;
5247
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005248 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005249 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005250 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005251 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005252
Douglas Gregor3545ff42009-09-21 16:56:56 +00005253 // The "template" keyword can follow "::" in the grammar, but only
5254 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005255 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005256 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005257 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005258
5259 // Add calls to overridden virtual functions, if there are any.
5260 //
5261 // FIXME: This isn't wonderful, because we don't know whether we're actually
5262 // in a context that permits expressions. This is a general issue with
5263 // qualified-id completions.
5264 if (!EnteringContext)
5265 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005266 Results.ExitScope();
5267
Eric Liufead6ae2017-12-13 10:26:49 +00005268 if (CodeCompleter->includeNamespaceLevelDecls() ||
5269 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005270 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005271 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5272 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005273 /*IncludeDependentBases=*/true,
5274 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005275 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005276
Eric Liu06d34022017-12-12 11:35:46 +00005277 auto CC = Results.getCompletionContext();
5278 CC.setCXXScopeSpecifier(SS);
5279
5280 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
5281 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005282}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005283
5284void Sema::CodeCompleteUsing(Scope *S) {
5285 if (!CodeCompleter)
5286 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005287
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005288 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005289 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005290 // This can be both a using alias or using
5291 // declaration, in the former we expect a new name and a
5292 // symbol in the latter case.
5293 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005294 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005295 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005296
Douglas Gregor3545ff42009-09-21 16:56:56 +00005297 // If we aren't in class scope, we could see the "namespace" keyword.
5298 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005299 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005300
5301 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005302 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005303 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005304 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005305 CodeCompleter->includeGlobals(),
5306 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005307 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005308
5309 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5310 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005311}
5312
5313void Sema::CodeCompleteUsingDirective(Scope *S) {
5314 if (!CodeCompleter)
5315 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005316
Douglas Gregor3545ff42009-09-21 16:56:56 +00005317 // After "using namespace", we expect to see a namespace name or namespace
5318 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005319 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005320 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005321 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005322 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005323 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005324 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005325 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005326 CodeCompleter->includeGlobals(),
5327 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005328 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005329 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5330 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005331}
5332
Fangrui Song050229d2018-11-24 00:14:31 +00005333void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005334 if (!CodeCompleter)
5335 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005336
Ted Kremenekc37877d2013-10-08 17:08:03 +00005337 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005338 if (!S->getParent())
5339 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005340
Fangrui Song050229d2018-11-24 00:14:31 +00005341 bool SuppressedGlobalResults =
5342 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005343
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005344 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005345 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005346 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005347 ? CodeCompletionContext::CCC_Namespace
5348 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005349 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005350
Douglas Gregor0ac41382010-09-23 23:01:17 +00005351 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005352 // We only want to see those namespaces that have already been defined
5353 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005354 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005355 // definition of each namespace.
5356 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005357 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005358 NS(Ctx->decls_begin()),
5359 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005360 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005361 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005362
5363 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005364 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005365 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005366 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005367 NS = OrigToLatest.begin(),
5368 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005369 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005370 Results.AddResult(
5371 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5372 nullptr),
5373 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005374 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005375 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005376
Fangrui Song050229d2018-11-24 00:14:31 +00005377 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5378 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005379}
5380
Fangrui Song050229d2018-11-24 00:14:31 +00005381void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005382 if (!CodeCompleter)
5383 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005384
Douglas Gregor3545ff42009-09-21 16:56:56 +00005385 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005386 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005387 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005388 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005389 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005390 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005391 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005392 CodeCompleter->includeGlobals(),
5393 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005394 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5395 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005396}
5397
Douglas Gregorc811ede2009-09-18 20:05:18 +00005398void Sema::CodeCompleteOperatorName(Scope *S) {
5399 if (!CodeCompleter)
5400 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005401
John McCall276321a2010-08-25 06:19:51 +00005402 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005403 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005404 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005405 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005406 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005407 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005408
Douglas Gregor3545ff42009-09-21 16:56:56 +00005409 // Add the names of overloadable operators.
Fangrui Song050229d2018-11-24 00:14:31 +00005410#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5411 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005412 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005413#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005414
Douglas Gregor3545ff42009-09-21 16:56:56 +00005415 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005416 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005417 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005418 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005419 CodeCompleter->includeGlobals(),
5420 CodeCompleter->loadExternal());
5421
Douglas Gregor3545ff42009-09-21 16:56:56 +00005422 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005423 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005424 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005425
5426 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5427 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005428}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005429
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005430void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005431 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005432 if (!ConstructorD)
5433 return;
5434
5435 AdjustDeclIfTemplate(ConstructorD);
5436
Fangrui Song050229d2018-11-24 00:14:31 +00005437 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005438 if (!Constructor)
5439 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005440
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005441 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005442 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005443 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005444 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005445
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005446 // Fill in any already-initialized fields or base classes.
5447 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5448 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005449 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005450 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005451 InitializedBases.insert(Context.getCanonicalType(
5452 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005453 else
Fangrui Song050229d2018-11-24 00:14:31 +00005454 InitializedFields.insert(
5455 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005456 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005457
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005458 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005459 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005460 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005461 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005462
5463 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5464 CodeCompletionBuilder Builder(Results.getAllocator(),
5465 Results.getCodeCompletionTUInfo());
5466 Builder.AddTypedTextChunk(Name);
5467 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005468 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005469 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005470 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005471 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5472 Builder);
5473 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5474 return Builder.TakeString();
5475 };
5476 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5477 const NamedDecl *ND) {
5478 CodeCompletionBuilder Builder(Results.getAllocator(),
5479 Results.getCodeCompletionTUInfo());
5480 Builder.AddTypedTextChunk(Name);
5481 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5482 Builder.AddPlaceholderChunk(Type);
5483 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5484 if (ND) {
5485 auto CCR = CodeCompletionResult(
5486 Builder.TakeString(), ND,
5487 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5488 if (isa<FieldDecl>(ND))
5489 CCR.CursorKind = CXCursor_MemberRef;
5490 return Results.AddResult(CCR);
5491 }
5492 return Results.AddResult(CodeCompletionResult(
5493 Builder.TakeString(),
5494 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5495 };
5496 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5497 const char *Name, const FieldDecl *FD) {
5498 if (!RD)
5499 return AddDefaultCtorInit(Name,
5500 FD ? Results.getAllocator().CopyString(
5501 FD->getType().getAsString(Policy))
5502 : Name,
5503 FD);
5504 auto Ctors = getConstructors(Context, RD);
5505 if (Ctors.begin() == Ctors.end())
5506 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005507 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005508 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5509 CCR.CursorKind = getCursorKindForDecl(Ctor);
5510 Results.AddResult(CCR);
5511 }
5512 };
5513 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5514 const char *BaseName =
5515 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5516 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5517 AddCtorsWithName(
5518 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5519 BaseName, nullptr);
5520 };
5521 auto AddField = [&](const FieldDecl *FD) {
5522 const char *FieldName =
5523 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5524 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5525 AddCtorsWithName(
5526 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5527 FieldName, FD);
5528 };
5529
Aaron Ballman574705e2014-03-13 15:41:46 +00005530 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005531 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5532 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005533 SawLastInitializer =
5534 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5535 Context.hasSameUnqualifiedType(
5536 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005537 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005538 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005539
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005540 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005541 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005542 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005543
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005544 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005545 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005546 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5547 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005548 SawLastInitializer =
5549 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5550 Context.hasSameUnqualifiedType(
5551 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005552 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005553 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005554
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005555 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005556 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005557 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005558
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005559 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005560 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005561 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5562 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005563 SawLastInitializer = !Initializers.empty() &&
5564 Initializers.back()->isAnyMemberInitializer() &&
5565 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005566 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005567 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005568
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005569 if (!Field->getDeclName())
5570 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005571
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005572 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005573 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005574 }
5575 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005576
Douglas Gregor0ac41382010-09-23 23:01:17 +00005577 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005578 Results.data(), Results.size());
5579}
5580
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005581/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005582static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005583 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005584 if (!DC)
5585 return false;
5586
5587 return DC->isFileContext();
5588}
5589
5590void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5591 bool AfterAmpersand) {
5592 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005593 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005594 CodeCompletionContext::CCC_Other);
5595 Results.EnterNewScope();
5596
5597 // Note what has already been captured.
5598 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5599 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005600 for (const auto &C : Intro.Captures) {
5601 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005602 IncludedThis = true;
5603 continue;
5604 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005605
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005606 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005607 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005608
Douglas Gregord8c61782012-02-15 15:34:24 +00005609 // Look for other capturable variables.
5610 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005611 for (const auto *D : S->decls()) {
5612 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005613 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005614 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005615
David Blaikie82e95a32014-11-19 07:49:47 +00005616 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005617 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005618 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005619 }
5620 }
5621
5622 // Add 'this', if it would be valid.
5623 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5624 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005625
Douglas Gregord8c61782012-02-15 15:34:24 +00005626 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005627
Douglas Gregord8c61782012-02-15 15:34:24 +00005628 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5629 Results.data(), Results.size());
5630}
5631
James Dennett596e4752012-06-14 03:11:41 +00005632/// Macro that optionally prepends an "@" to the string literal passed in via
5633/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005634#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005635
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005636static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005637 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005638 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005639 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005640 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005641
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005642 CodeCompletionBuilder Builder(Results.getAllocator(),
5643 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005644 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005645 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005646 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005647 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5648 Builder.AddPlaceholderChunk("property");
5649 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005650
Douglas Gregorf1934162010-01-13 21:24:21 +00005651 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005652 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005653 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5654 Builder.AddPlaceholderChunk("property");
5655 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005656 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005657}
5658
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005659static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005660 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005661 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005662
Douglas Gregorf1934162010-01-13 21:24:21 +00005663 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005664 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005665
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005666 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005667 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005668 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005669
Douglas Gregorf1934162010-01-13 21:24:21 +00005670 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005671 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005672
Douglas Gregorf1934162010-01-13 21:24:21 +00005673 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005674 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005675 }
5676}
5677
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005678static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005679 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005680 CodeCompletionBuilder Builder(Results.getAllocator(),
5681 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005682
Douglas Gregorf1934162010-01-13 21:24:21 +00005683 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005684 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005685 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5686 Builder.AddPlaceholderChunk("name");
5687 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005688
Douglas Gregorf4c33342010-05-28 00:22:41 +00005689 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005690 // @interface name
5691 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005692 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005693 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005694 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5695 Builder.AddPlaceholderChunk("class");
5696 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005697
Douglas Gregorf4c33342010-05-28 00:22:41 +00005698 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005699 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005700 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5701 Builder.AddPlaceholderChunk("protocol");
5702 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005703
Douglas Gregorf4c33342010-05-28 00:22:41 +00005704 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005705 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005706 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5707 Builder.AddPlaceholderChunk("class");
5708 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005709 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005710
Douglas Gregorf1934162010-01-13 21:24:21 +00005711 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005712 Builder.AddTypedTextChunk(
5713 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005714 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5715 Builder.AddPlaceholderChunk("alias");
5716 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5717 Builder.AddPlaceholderChunk("class");
5718 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005719
5720 if (Results.getSema().getLangOpts().Modules) {
5721 // @import name
5722 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5723 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5724 Builder.AddPlaceholderChunk("module");
5725 Results.AddResult(Result(Builder.TakeString()));
5726 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005727}
5728
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005729void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005730 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005731 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005732 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005733 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005734 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005735 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005736 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005737 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005738 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005739 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005740 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005741 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5742 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005743}
5744
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005745static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005746 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005747 CodeCompletionBuilder Builder(Results.getAllocator(),
5748 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005749
5750 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005751 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005752 if (Results.getSema().getLangOpts().CPlusPlus ||
5753 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005754 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005755 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005756 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005757 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5758 Builder.AddPlaceholderChunk("type-name");
5759 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5760 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005761
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005762 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005763 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005764 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005765 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5766 Builder.AddPlaceholderChunk("protocol-name");
5767 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5768 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005769
5770 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005771 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005772 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005773 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5774 Builder.AddPlaceholderChunk("selector");
5775 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5776 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005777
5778 // @"string"
5779 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005780 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005781 Builder.AddPlaceholderChunk("string");
5782 Builder.AddTextChunk("\"");
5783 Results.AddResult(Result(Builder.TakeString()));
5784
Douglas Gregor951de302012-07-17 23:24:47 +00005785 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005786 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005787 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005788 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005789 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5790 Results.AddResult(Result(Builder.TakeString()));
5791
Douglas Gregor951de302012-07-17 23:24:47 +00005792 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005793 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005794 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005795 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005796 Builder.AddChunk(CodeCompletionString::CK_Colon);
5797 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5798 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005799 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5800 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005801
Douglas Gregor951de302012-07-17 23:24:47 +00005802 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005803 Builder.AddResultTypeChunk("id");
5804 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005805 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005806 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5807 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005808}
5809
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005810static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005811 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005812 CodeCompletionBuilder Builder(Results.getAllocator(),
5813 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005814
Douglas Gregorf4c33342010-05-28 00:22:41 +00005815 if (Results.includeCodePatterns()) {
5816 // @try { statements } @catch ( declaration ) { statements } @finally
5817 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005818 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005819 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5820 Builder.AddPlaceholderChunk("statements");
5821 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5822 Builder.AddTextChunk("@catch");
5823 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5824 Builder.AddPlaceholderChunk("parameter");
5825 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5826 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5827 Builder.AddPlaceholderChunk("statements");
5828 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5829 Builder.AddTextChunk("@finally");
5830 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5831 Builder.AddPlaceholderChunk("statements");
5832 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5833 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005834 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005835
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005836 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005837 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005838 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5839 Builder.AddPlaceholderChunk("expression");
5840 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005841
Douglas Gregorf4c33342010-05-28 00:22:41 +00005842 if (Results.includeCodePatterns()) {
5843 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005844 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005845 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5846 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5847 Builder.AddPlaceholderChunk("expression");
5848 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5849 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5850 Builder.AddPlaceholderChunk("statements");
5851 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5852 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005853 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005854}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005855
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005856static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005857 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005858 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005859 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5860 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5861 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005862 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005863 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005864}
5865
5866void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005867 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005868 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005869 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005870 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005871 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005872 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005873 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5874 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005875}
5876
5877void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005878 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005879 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005880 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005881 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005882 AddObjCStatementResults(Results, false);
5883 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005884 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005885 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5886 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005887}
5888
5889void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005890 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005891 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005892 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005893 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005894 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005895 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005896 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5897 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005898}
5899
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005900/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005901/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005902static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005903 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005904 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005905 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005906
Bill Wendling44426052012-12-20 19:22:21 +00005907 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005908
Douglas Gregore6078da2009-11-19 00:14:45 +00005909 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005910 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5911 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005912 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005913
Jordan Rose53cb2f32012-08-20 20:01:13 +00005914 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00005915 unsigned AssignCopyRetMask =
5916 Attributes &
5917 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
5918 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
5919 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
5920 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005921 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005922 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005923 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005924 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5925 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005926 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005927
Douglas Gregore6078da2009-11-19 00:14:45 +00005928 return false;
5929}
5930
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005931void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005932 if (!CodeCompleter)
5933 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005934
Bill Wendling44426052012-12-20 19:22:21 +00005935 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005936
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005937 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005938 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005939 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005940 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005941 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005942 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005943 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005944 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005945 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005946 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5947 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005948 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005949 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005950 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005951 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005952 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005953 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005954 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005955 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005956 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005957 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005958 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005959 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005960
5961 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005962 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005963 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005964 Results.AddResult(CodeCompletionResult("weak"));
5965
Bill Wendling44426052012-12-20 19:22:21 +00005966 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005967 CodeCompletionBuilder Setter(Results.getAllocator(),
5968 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005969 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005970 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005971 Setter.AddPlaceholderChunk("method");
5972 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005973 }
Bill Wendling44426052012-12-20 19:22:21 +00005974 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005975 CodeCompletionBuilder Getter(Results.getAllocator(),
5976 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005977 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005978 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005979 Getter.AddPlaceholderChunk("method");
5980 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005981 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005982 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5983 Results.AddResult(CodeCompletionResult("nonnull"));
5984 Results.AddResult(CodeCompletionResult("nullable"));
5985 Results.AddResult(CodeCompletionResult("null_unspecified"));
5986 Results.AddResult(CodeCompletionResult("null_resettable"));
5987 }
Steve Naroff936354c2009-10-08 21:55:05 +00005988 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005989 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5990 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005991}
Steve Naroffeae65032009-11-07 02:08:14 +00005992
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005993/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005994/// via code completion.
5995enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005996 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5997 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00005998 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005999};
6000
Fangrui Song050229d2018-11-24 00:14:31 +00006001static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006002 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006003 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006004 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006005 if (NumSelIdents > Sel.getNumArgs())
6006 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006007
Douglas Gregor67c692c2010-08-26 15:07:07 +00006008 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00006009 case MK_Any:
6010 break;
6011 case MK_ZeroArgSelector:
6012 return Sel.isUnarySelector();
6013 case MK_OneArgSelector:
6014 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006015 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006016
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006017 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
6018 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006019
Douglas Gregor67c692c2010-08-26 15:07:07 +00006020 for (unsigned I = 0; I != NumSelIdents; ++I)
6021 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
6022 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006023
Douglas Gregor67c692c2010-08-26 15:07:07 +00006024 return true;
6025}
6026
Douglas Gregorc8537c52009-11-19 07:41:15 +00006027static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
6028 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006029 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006030 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006031 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006032 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006033}
Douglas Gregor1154e272010-09-16 16:06:31 +00006034
Fangrui Song050229d2018-11-24 00:14:31 +00006035/// A set of selectors, which is used to avoid introducing multiple
6036/// completions with the same selector into the result set.
6037typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00006038
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006039/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006040/// container to the set of results.
6041///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006042/// The container will be a class, protocol, category, or implementation of
6043/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006044/// the superclasses of classes along with their categories, protocols, and
6045/// implementations.
6046///
6047/// \param Container the container in which we'll look to find methods.
6048///
James Dennett596e4752012-06-14 03:11:41 +00006049/// \param WantInstanceMethods Whether to add instance methods (only); if
6050/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006051///
6052/// \param CurContext the context in which we're performing the lookup that
6053/// finds methods.
6054///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006055/// \param AllowSameLength Whether we allow a method to be added to the list
6056/// when it has the same number of parameters as we have selector identifiers.
6057///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006058/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006059static void AddObjCMethods(ObjCContainerDecl *Container,
6060 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006061 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006062 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006063 VisitedSelectorSet &Selectors, bool AllowSameLength,
6064 ResultBuilder &Results, bool InOriginalClass = true,
6065 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00006066 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006067 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00006068 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00006069 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00006070 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00006071 // The instance methods on the root class can be messaged via the
6072 // metaclass.
6073 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00006074 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006075 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00006076 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006077 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00006078 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00006079
David Blaikie82e95a32014-11-19 07:49:47 +00006080 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006081 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006082
6083 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006084 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00006085 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00006086 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00006087 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00006088 Results.MaybeAddResult(R, CurContext);
6089 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006090 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006091
Douglas Gregorf37c9492010-09-16 15:34:59 +00006092 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006093 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00006094 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006095 const ObjCList<ObjCProtocolDecl> &Protocols =
6096 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006097 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006098 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006099 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006100 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6101 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00006102 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00006103 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006104
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006105 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006106 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006107
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006108 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006109 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006110 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6111 Selectors, AllowSameLength, Results, false, IsRootClass);
6112
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006113 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00006114 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006115 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006116 CurContext, Selectors, AllowSameLength, Results,
6117 InOriginalClass, IsRootClass);
6118
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006119 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00006120 const ObjCList<ObjCProtocolDecl> &Protocols =
6121 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006122 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6123 E = Protocols.end();
6124 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006125 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6126 Selectors, AllowSameLength, Results, false, IsRootClass);
6127
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006128 // Add methods in category implementations.
6129 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006130 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6131 Selectors, AllowSameLength, Results, InOriginalClass,
6132 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006133 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006134
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006135 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006136 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006137 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006138 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6139 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6140 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006141
6142 // Add methods in our implementation, if any.
6143 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006144 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6145 Selectors, AllowSameLength, Results, InOriginalClass,
6146 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006147}
6148
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006149void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006150 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006151 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006152 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006153 if (ObjCCategoryDecl *Category =
6154 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006155 Class = Category->getClassInterface();
6156
6157 if (!Class)
6158 return;
6159 }
6160
6161 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006162 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006163 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006164 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006165 Results.EnterNewScope();
6166
Douglas Gregor1154e272010-09-16 16:06:31 +00006167 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006168 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006169 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006170 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006171 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6172 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006173}
6174
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006175void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006176 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006177 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006178 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006179 if (ObjCCategoryDecl *Category =
6180 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006181 Class = Category->getClassInterface();
6182
6183 if (!Class)
6184 return;
6185 }
6186
6187 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006188 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006189 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006190 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006191 Results.EnterNewScope();
6192
Douglas Gregor1154e272010-09-16 16:06:31 +00006193 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006194 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6195 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006196
6197 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006198 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6199 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006200}
6201
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006202void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6203 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006204 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006205 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006206 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006207 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006208
Douglas Gregor99fa2642010-08-24 01:06:58 +00006209 // Add context-sensitive, Objective-C parameter-passing keywords.
6210 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006211 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006212 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6213 Results.AddResult("in");
6214 Results.AddResult("inout");
6215 AddedInOut = true;
6216 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006217 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006218 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6219 Results.AddResult("out");
6220 if (!AddedInOut)
6221 Results.AddResult("inout");
6222 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006223 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006224 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6225 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006226 Results.AddResult("bycopy");
6227 Results.AddResult("byref");
6228 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006229 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006230 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6231 Results.AddResult("nonnull");
6232 Results.AddResult("nullable");
6233 Results.AddResult("null_unspecified");
6234 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006235
6236 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006237 // identifier IBAction refers to a macro, provide a completion item for
6238 // an action, e.g.,
6239 // IBAction)<#selector#>:(id)sender
6240 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006241 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006242 CodeCompletionBuilder Builder(Results.getAllocator(),
6243 Results.getCodeCompletionTUInfo(),
6244 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006245 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006246 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006247 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006248 Builder.AddChunk(CodeCompletionString::CK_Colon);
6249 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006250 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006251 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006252 Builder.AddTextChunk("sender");
6253 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6254 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006255
6256 // If we're completing the return type, provide 'instancetype'.
6257 if (!IsParameter) {
6258 Results.AddResult(CodeCompletionResult("instancetype"));
6259 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006260
Douglas Gregor99fa2642010-08-24 01:06:58 +00006261 // Add various builtin type names and specifiers.
6262 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6263 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006264
Douglas Gregor99fa2642010-08-24 01:06:58 +00006265 // Add the various type names
6266 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6267 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6268 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006269 CodeCompleter->includeGlobals(),
6270 CodeCompleter->loadExternal());
6271
Douglas Gregor99fa2642010-08-24 01:06:58 +00006272 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006273 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006274
Eric Liuf5ba09f2018-07-04 10:01:18 +00006275 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006276 Results.data(), Results.size());
6277}
6278
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006279/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006280/// that it has some more-specific class type based on knowledge of
6281/// common uses of Objective-C. This routine returns that class type,
6282/// or NULL if no better result could be determined.
6283static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006284 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006285 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006286 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006287
6288 Selector Sel = Msg->getSelector();
6289 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006290 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006291
6292 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6293 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006294 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006295
6296 ObjCMethodDecl *Method = Msg->getMethodDecl();
6297 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006298 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006299
6300 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006301 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006302 switch (Msg->getReceiverKind()) {
6303 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006304 if (const ObjCObjectType *ObjType =
6305 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006306 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006307 break;
6308
6309 case ObjCMessageExpr::Instance: {
6310 QualType T = Msg->getInstanceReceiver()->getType();
6311 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6312 IFace = Ptr->getInterfaceDecl();
6313 break;
6314 }
6315
6316 case ObjCMessageExpr::SuperInstance:
6317 case ObjCMessageExpr::SuperClass:
6318 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006319 }
6320
6321 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006322 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006323
6324 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6325 if (Method->isInstanceMethod())
6326 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006327 .Case("retain", IFace)
6328 .Case("strong", IFace)
6329 .Case("autorelease", IFace)
6330 .Case("copy", IFace)
6331 .Case("copyWithZone", IFace)
6332 .Case("mutableCopy", IFace)
6333 .Case("mutableCopyWithZone", IFace)
6334 .Case("awakeFromCoder", IFace)
6335 .Case("replacementObjectFromCoder", IFace)
6336 .Case("class", IFace)
6337 .Case("classForCoder", IFace)
6338 .Case("superclass", Super)
6339 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006340
6341 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006342 .Case("new", IFace)
6343 .Case("alloc", IFace)
6344 .Case("allocWithZone", IFace)
6345 .Case("class", IFace)
6346 .Case("superclass", Super)
6347 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006348}
6349
Douglas Gregor6fc04132010-08-27 15:10:57 +00006350// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006351// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006352// function.
6353///
6354/// \param S The semantic analysis object.
6355///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006356/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006357/// the "super" keyword. Otherwise, we just need to provide the arguments.
6358///
6359/// \param SelIdents The identifiers in the selector that have already been
6360/// provided as arguments for a send to "super".
6361///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006362/// \param Results The set of results to augment.
6363///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006364/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006365/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006366static ObjCMethodDecl *
6367AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6368 ArrayRef<IdentifierInfo *> SelIdents,
6369 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006370 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6371 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006372 return nullptr;
6373
Douglas Gregor6fc04132010-08-27 15:10:57 +00006374 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6375 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006376 return nullptr;
6377
Douglas Gregor6fc04132010-08-27 15:10:57 +00006378 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006379 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006380 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6381 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006382 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006383 CurMethod->isInstanceMethod());
6384
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006385 // Check in categories or class extensions.
6386 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006387 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006388 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006389 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006390 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006391 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006392 }
6393 }
6394
Douglas Gregor6fc04132010-08-27 15:10:57 +00006395 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006396 return nullptr;
6397
Douglas Gregor6fc04132010-08-27 15:10:57 +00006398 // Check whether the superclass method has the same signature.
6399 if (CurMethod->param_size() != SuperMethod->param_size() ||
6400 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006401 return nullptr;
6402
Douglas Gregor6fc04132010-08-27 15:10:57 +00006403 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006404 CurPEnd = CurMethod->param_end(),
6405 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006406 CurP != CurPEnd; ++CurP, ++SuperP) {
6407 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006408 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006409 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006410 return nullptr;
6411
Douglas Gregor6fc04132010-08-27 15:10:57 +00006412 // Make sure we have a parameter name to forward!
6413 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006414 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006415 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006416
Douglas Gregor6fc04132010-08-27 15:10:57 +00006417 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006418 CodeCompletionBuilder Builder(Results.getAllocator(),
6419 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006420
Douglas Gregor6fc04132010-08-27 15:10:57 +00006421 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006422 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006423 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006424
6425 // If we need the "super" keyword, add it (plus some spacing).
6426 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006427 Builder.AddTypedTextChunk("super");
6428 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006429 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006430
Douglas Gregor6fc04132010-08-27 15:10:57 +00006431 Selector Sel = CurMethod->getSelector();
6432 if (Sel.isUnarySelector()) {
6433 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006434 Builder.AddTextChunk(
6435 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006436 else
Fangrui Song050229d2018-11-24 00:14:31 +00006437 Builder.AddTypedTextChunk(
6438 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006439 } else {
6440 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6441 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006442 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006443 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006444
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006445 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006446 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006447 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006448 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006449 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006450 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006451 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006452 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006453 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006454 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006455 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006456 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006457 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006458 }
6459 }
6460 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006461
Douglas Gregor78254c82012-03-27 23:34:16 +00006462 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6463 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006464 return SuperMethod;
6465}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006466
Douglas Gregora817a192010-05-27 23:06:34 +00006467void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006468 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006469 ResultBuilder Results(
6470 *this, CodeCompleter->getAllocator(),
6471 CodeCompleter->getCodeCompletionTUInfo(),
6472 CodeCompletionContext::CCC_ObjCMessageReceiver,
6473 getLangOpts().CPlusPlus11
6474 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6475 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006476
Douglas Gregora817a192010-05-27 23:06:34 +00006477 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6478 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006479 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006480 CodeCompleter->includeGlobals(),
6481 CodeCompleter->loadExternal());
6482
Douglas Gregora817a192010-05-27 23:06:34 +00006483 // If we are in an Objective-C method inside a class that has a superclass,
6484 // add "super" as an option.
6485 if (ObjCMethodDecl *Method = getCurMethodDecl())
6486 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006487 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006488 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006489
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006490 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006491 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006492
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006493 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006494 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006495
Douglas Gregora817a192010-05-27 23:06:34 +00006496 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006497
Douglas Gregora817a192010-05-27 23:06:34 +00006498 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006499 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006500 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006501 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006502}
6503
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006504void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006505 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006506 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006507 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006508 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6509 // Figure out which interface we're in.
6510 CDecl = CurMethod->getClassInterface();
6511 if (!CDecl)
6512 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006513
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006514 // Find the superclass of this class.
6515 CDecl = CDecl->getSuperClass();
6516 if (!CDecl)
6517 return;
6518
6519 if (CurMethod->isInstanceMethod()) {
6520 // We are inside an instance method, which means that the message
6521 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006522 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006523 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006524 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006525 }
6526
6527 // Fall through to send to the superclass in CDecl.
6528 } else {
6529 // "super" may be the name of a type or variable. Figure out which
6530 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006531 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006532 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006533 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6534 // "super" names an interface. Use it.
6535 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006536 if (const ObjCObjectType *Iface =
6537 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006538 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006539 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6540 // "super" names an unresolved type; we can't be more specific.
6541 } else {
6542 // Assume that "super" names some kind of value and parse that way.
6543 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006544 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006545 UnqualifiedId id;
6546 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006547 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6548 /*HasTrailingLParen=*/false,
6549 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006550 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006551 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006552 }
6553
6554 // Fall through
6555 }
6556
John McCallba7bf592010-08-24 05:47:05 +00006557 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006558 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006559 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006560 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006561 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006562 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006563}
6564
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006565/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006566/// send, determine the preferred type (if any) for that argument expression.
6567static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6568 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006569 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006570 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006571
Douglas Gregor74661272010-09-21 00:03:25 +00006572 QualType PreferredType;
6573 unsigned BestPriority = CCP_Unlikely * 2;
6574 Result *ResultsData = Results.data();
6575 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6576 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006577 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006578 isa<ObjCMethodDecl>(R.Declaration)) {
6579 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006580 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006581 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006582 QualType MyPreferredType =
6583 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006584 if (R.Priority < BestPriority || PreferredType.isNull()) {
6585 BestPriority = R.Priority;
6586 PreferredType = MyPreferredType;
6587 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6588 MyPreferredType)) {
6589 PreferredType = QualType();
6590 }
6591 }
6592 }
6593 }
6594 }
6595
6596 return PreferredType;
6597}
6598
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006599static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006600 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006601 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006602 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006603 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006604 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006605 ObjCInterfaceDecl *CDecl = nullptr;
6606
Douglas Gregor8ce33212009-11-17 17:59:40 +00006607 // If the given name refers to an interface type, retrieve the
6608 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006609 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006610 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006611 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006612 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6613 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006614 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006615
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006616 // Add all of the factory methods in this Objective-C class, its protocols,
6617 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006618 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006619
6620 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006621 // completion.
6622 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006623 if (ObjCMethodDecl *SuperMethod =
6624 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006625 Results.Ignore(SuperMethod);
6626 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006627
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006628 // If we're inside an Objective-C method definition, prefer its selector to
6629 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006630 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006631 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006632
Douglas Gregor1154e272010-09-16 16:06:31 +00006633 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006634 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006635 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6636 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006637 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006638 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006639
Douglas Gregord720daf2010-04-06 17:30:22 +00006640 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006641 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006642 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006643 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006644 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006645 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006646 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006647 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006648 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006649
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006650 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006651 }
6652 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006653
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006654 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006655 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006656 M != MEnd; ++M) {
6657 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006658 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006659 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006660 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006661
Nico Weber2e0c8f72014-12-27 03:58:08 +00006662 Result R(MethList->getMethod(),
6663 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006664 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006665 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006666 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006667 }
6668 }
6669 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006670
6671 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006672}
Douglas Gregor6285f752010-04-06 16:40:00 +00006673
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006674void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006675 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006676 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006677 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006678
Douglas Gregor63745d52011-07-21 01:05:26 +00006679 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006680
Fangrui Song050229d2018-11-24 00:14:31 +00006681 ResultBuilder Results(
6682 *this, CodeCompleter->getAllocator(),
6683 CodeCompleter->getCodeCompletionTUInfo(),
6684 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6685 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006686
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006687 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006688 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006689
6690 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006691 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006692 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006693 // code-complete the expression using the corresponding parameter type as
6694 // our preferred type, improving completion results.
6695 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006696 QualType PreferredType =
6697 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006698 if (PreferredType.isNull())
6699 CodeCompleteOrdinaryName(S, PCC_Expression);
6700 else
6701 CodeCompleteExpression(S, PreferredType);
6702 return;
6703 }
6704
Fangrui Song050229d2018-11-24 00:14:31 +00006705 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006706 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006707}
6708
Richard Trieu2bd04012011-09-09 02:00:50 +00006709void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006710 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006711 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006712 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006713 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006714
Steve Naroffeae65032009-11-07 02:08:14 +00006715 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006716
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006717 // If necessary, apply function/array conversion to the receiver.
6718 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006719 if (RecExpr) {
6720 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6721 if (Conv.isInvalid()) // conversion failed. bail.
6722 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006723 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006724 }
Fangrui Song050229d2018-11-24 00:14:31 +00006725 QualType ReceiverType = RecExpr
6726 ? RecExpr->getType()
6727 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006728 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006729 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006730
Douglas Gregordc520b02010-11-08 21:12:30 +00006731 // If we're messaging an expression with type "id" or "Class", check
6732 // whether we know something special about the receiver that allows
6733 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006734 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006735 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6736 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006737 return CodeCompleteObjCClassMessage(
6738 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6739 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006740
Fangrui Song050229d2018-11-24 00:14:31 +00006741 ReceiverType =
6742 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006743 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006744 } else if (RecExpr && getLangOpts().CPlusPlus) {
6745 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6746 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006747 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006748 ReceiverType = RecExpr->getType();
6749 }
6750 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006751
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006752 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006753 ResultBuilder Results(
6754 *this, CodeCompleter->getAllocator(),
6755 CodeCompleter->getCodeCompletionTUInfo(),
6756 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6757 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006758
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006759 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006760
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006761 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006762 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006763 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006764 if (ObjCMethodDecl *SuperMethod =
6765 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006766 Results.Ignore(SuperMethod);
6767 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006768
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006769 // If we're inside an Objective-C method definition, prefer its selector to
6770 // others.
6771 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6772 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006773
Douglas Gregor1154e272010-09-16 16:06:31 +00006774 // Keep track of the selectors we've already added.
6775 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006776
Douglas Gregora3329fa2009-11-18 00:06:18 +00006777 // Handle messages to Class. This really isn't a message to an instance
6778 // method, so we treat it the same way we would treat a message send to a
6779 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006780 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006781 ReceiverType->isObjCQualifiedClassType()) {
6782 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6783 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006784 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6785 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006786 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006787 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006788 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006789 else if (const ObjCObjectPointerType *QualID =
6790 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006791 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006792 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006793 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6794 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006795 }
6796 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006797 else if (const ObjCObjectPointerType *IFacePtr =
6798 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006799 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006800 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006801 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006802
Douglas Gregora3329fa2009-11-18 00:06:18 +00006803 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006804 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006805 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6806 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006807 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006808 // Handle messages to "id".
6809 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006810 // We're messaging "id", so provide all instance methods we know
6811 // about as code-completion results.
6812
6813 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006814 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006815 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006816 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6817 I != N; ++I) {
6818 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006819 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006820 continue;
6821
Sebastian Redl75d8a322010-08-02 23:18:59 +00006822 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006823 }
6824 }
6825
Sebastian Redl75d8a322010-08-02 23:18:59 +00006826 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6827 MEnd = MethodPool.end();
6828 M != MEnd; ++M) {
6829 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006830 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006831 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006832 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006833
Nico Weber2e0c8f72014-12-27 03:58:08 +00006834 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006835 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006836
Nico Weber2e0c8f72014-12-27 03:58:08 +00006837 Result R(MethList->getMethod(),
6838 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006839 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006840 R.AllParametersAreInformative = false;
6841 Results.MaybeAddResult(R, CurContext);
6842 }
6843 }
6844 }
Steve Naroffeae65032009-11-07 02:08:14 +00006845 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006846
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006847 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006848 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006849 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006850 // code-complete the expression using the corresponding parameter type as
6851 // our preferred type, improving completion results.
6852 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006853 QualType PreferredType =
6854 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006855 if (PreferredType.isNull())
6856 CodeCompleteOrdinaryName(S, PCC_Expression);
6857 else
6858 CodeCompleteExpression(S, PreferredType);
6859 return;
6860 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006861
Fangrui Song050229d2018-11-24 00:14:31 +00006862 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6863 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006864}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006865
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006866void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006867 DeclGroupPtrTy IterationVar) {
6868 CodeCompleteExpressionData Data;
6869 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006870
Douglas Gregor68762e72010-08-23 21:17:50 +00006871 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006872 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006873 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6874 if (*I)
6875 Data.IgnoreDecls.push_back(*I);
6876 }
6877 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006878
Douglas Gregor68762e72010-08-23 21:17:50 +00006879 CodeCompleteExpression(S, Data);
6880}
6881
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006882void Sema::CodeCompleteObjCSelector(Scope *S,
6883 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006884 // If we have an external source, load the entire class method
6885 // pool from the AST file.
6886 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00006887 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
6888 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006889 Selector Sel = ExternalSource->GetExternalSelector(I);
6890 if (Sel.isNull() || MethodPool.count(Sel))
6891 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006892
Douglas Gregor67c692c2010-08-26 15:07:07 +00006893 ReadMethodPool(Sel);
6894 }
6895 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006896
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006897 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006898 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006899 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006900 Results.EnterNewScope();
6901 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006902 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006903 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006904
Douglas Gregor67c692c2010-08-26 15:07:07 +00006905 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006906 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006907 continue;
6908
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006909 CodeCompletionBuilder Builder(Results.getAllocator(),
6910 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006911 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006912 Builder.AddTypedTextChunk(
6913 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006914 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006915 continue;
6916 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006917
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006918 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006919 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006920 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006921 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006922 Builder.AddInformativeChunk(
6923 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006924 Accumulator.clear();
6925 }
6926 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006927
Benjamin Kramer632500c2011-07-26 16:59:25 +00006928 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006929 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006930 }
Fangrui Song050229d2018-11-24 00:14:31 +00006931 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006932 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006933 }
6934 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006935
6936 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006937 Results.data(), Results.size());
6938}
6939
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006940/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006941/// (translation unit) context.
6942static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006943 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006944 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006945 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006946
Aaron Ballman629afae2014-03-07 19:56:05 +00006947 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006948 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006949 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006950 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00006951 Results.AddResult(
6952 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
6953 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006954 }
6955}
6956
Craig Topper883dd332015-12-24 23:58:11 +00006957void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00006958 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006959 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006960 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006961 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006962
Chandler Carruthede11632016-11-04 06:06:50 +00006963 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006964 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006965
Douglas Gregora3b23b02010-12-09 21:44:02 +00006966 // Tell the result set to ignore all of the protocols we have
6967 // already seen.
6968 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006969 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00006970 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006971 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006972
Douglas Gregora3b23b02010-12-09 21:44:02 +00006973 // Add all protocols.
6974 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6975 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006976
Douglas Gregora3b23b02010-12-09 21:44:02 +00006977 Results.ExitScope();
6978 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006979
6980 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6981 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006982}
6983
6984void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006985 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006986 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006987 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006988
Chandler Carruthede11632016-11-04 06:06:50 +00006989 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006990 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006991
Douglas Gregora3b23b02010-12-09 21:44:02 +00006992 // Add all protocols.
6993 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6994 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006995
Douglas Gregora3b23b02010-12-09 21:44:02 +00006996 Results.ExitScope();
6997 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006998
6999 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7000 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00007001}
Douglas Gregor49c22a72009-11-18 16:26:39 +00007002
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007003/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00007004/// the given (translation unit) context.
7005static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
7006 bool OnlyForwardDeclarations,
7007 bool OnlyUnimplemented,
7008 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007009 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007010
Aaron Ballman629afae2014-03-07 19:56:05 +00007011 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00007012 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007013 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00007014 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00007015 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00007016 Results.AddResult(
7017 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
7018 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007019 }
7020}
7021
Eric Liuf5ba09f2018-07-04 10:01:18 +00007022void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007023 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007024 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007025 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007026 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007027
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007028 if (CodeCompleter->includeGlobals()) {
7029 // Add all classes.
7030 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7031 false, Results);
7032 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007033
Douglas Gregor49c22a72009-11-18 16:26:39 +00007034 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007035
Eric Liuf5ba09f2018-07-04 10:01:18 +00007036 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7037 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007038}
7039
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007040void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007041 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007042 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007043 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007044 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007045 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007046
Douglas Gregor49c22a72009-11-18 16:26:39 +00007047 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00007048 NamedDecl *CurClass =
7049 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007050 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00007051 Results.Ignore(CurClass);
7052
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007053 if (CodeCompleter->includeGlobals()) {
7054 // Add all classes.
7055 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7056 false, Results);
7057 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007058
Douglas Gregor49c22a72009-11-18 16:26:39 +00007059 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007060
Eric Liuf5ba09f2018-07-04 10:01:18 +00007061 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7062 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007063}
7064
Eric Liuf5ba09f2018-07-04 10:01:18 +00007065void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007066 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007067 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007068 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007069 Results.EnterNewScope();
7070
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007071 if (CodeCompleter->includeGlobals()) {
7072 // Add all unimplemented classes.
7073 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7074 true, Results);
7075 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007076
Douglas Gregor49c22a72009-11-18 16:26:39 +00007077 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007078
Eric Liuf5ba09f2018-07-04 10:01:18 +00007079 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7080 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007081}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007082
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007083void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007084 IdentifierInfo *ClassName,
7085 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007086 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007087
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007088 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007089 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007090 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007091
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007092 // Ignore any categories we find that have already been implemented by this
7093 // interface.
7094 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00007095 NamedDecl *CurClass =
7096 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
7097 if (ObjCInterfaceDecl *Class =
7098 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007099 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007100 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007101 }
7102
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007103 // Add all of the categories we know about.
7104 Results.EnterNewScope();
7105 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007106 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00007107 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00007108 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00007109 Results.AddResult(
7110 Result(Category, Results.getBasePriority(Category), nullptr),
7111 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007112 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007113
7114 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7115 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007116}
7117
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007118void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007119 IdentifierInfo *ClassName,
7120 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007121 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007122
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007123 // Find the corresponding interface. If we couldn't find the interface, the
7124 // program itself is ill-formed. However, we'll try to be helpful still by
7125 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00007126 NamedDecl *CurClass =
7127 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007128 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
7129 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007130 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007131
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007132 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007133 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007134 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007135
7136 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007137 // declarations in this class and any of its superclasses, except for
7138 // already-implemented categories in the class itself.
7139 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7140 Results.EnterNewScope();
7141 bool IgnoreImplemented = true;
7142 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007143 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007144 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007145 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007146 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7147 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007148 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007149
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007150 Class = Class->getSuperClass();
7151 IgnoreImplemented = false;
7152 }
7153 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007154
7155 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7156 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007157}
Douglas Gregor5d649882009-11-18 22:32:06 +00007158
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007159void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007160 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007161 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007162 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007163
7164 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007165 ObjCContainerDecl *Container =
7166 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7167 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7168 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007169 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007170
7171 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007172 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007173 for (const auto *D : Container->decls())
7174 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007175 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007176
Douglas Gregor5d649882009-11-18 22:32:06 +00007177 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007178 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007179 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007180 if (ObjCImplementationDecl *ClassImpl =
7181 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007182 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007183 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007184 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007185 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007186 AddObjCProperties(CCContext,
7187 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007188 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007189 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007190 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007191
7192 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7193 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007194}
7195
Fangrui Song050229d2018-11-24 00:14:31 +00007196void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7197 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007198 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007199 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007200 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007201 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007202
7203 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007204 ObjCContainerDecl *Container =
7205 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7206 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7207 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007208 return;
7209
Douglas Gregor5d649882009-11-18 22:32:06 +00007210 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007211 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007212 if (ObjCImplementationDecl *ClassImpl =
7213 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007214 Class = ClassImpl->getClassInterface();
7215 else
Fangrui Song050229d2018-11-24 00:14:31 +00007216 Class = cast<ObjCCategoryImplDecl>(Container)
7217 ->getCategoryDecl()
7218 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007219
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007220 // Determine the type of the property we're synthesizing.
7221 QualType PropertyType = Context.getObjCIdType();
7222 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007223 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7224 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007225 PropertyType =
7226 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007227
7228 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007229 Results.setPreferredType(PropertyType);
7230 }
7231 }
7232
Douglas Gregor5d649882009-11-18 22:32:06 +00007233 // Add all of the instance variables in this class and its superclasses.
7234 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007235 bool SawSimilarlyNamedIvar = false;
7236 std::string NameWithPrefix;
7237 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007238 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007239 std::string NameWithSuffix = PropertyName->getName().str();
7240 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007241 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007242 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007243 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007244 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7245 CurContext, nullptr, false);
7246
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007247 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007248 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007249 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007250 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007251 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007252 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007253
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007254 // Reduce the priority of this result by one, to give it a slight
7255 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007256 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007257 Results.data()[Results.size() - 1].Kind ==
7258 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007259 Results.data()[Results.size() - 1].Declaration == Ivar)
7260 Results.data()[Results.size() - 1].Priority--;
7261 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007262 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007263 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007264
Douglas Gregor331faa02011-04-18 14:13:53 +00007265 if (!SawSimilarlyNamedIvar) {
7266 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007267 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007268 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007269 typedef CodeCompletionResult Result;
7270 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007271 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007272 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007273
Douglas Gregor75acd922011-09-27 23:30:47 +00007274 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007275 Builder.AddResultTypeChunk(
7276 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007277 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007278 Results.AddResult(
7279 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007280 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007281
Douglas Gregor5d649882009-11-18 22:32:06 +00007282 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007283
7284 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7285 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007286}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007287
Douglas Gregor416b5752010-08-25 01:08:01 +00007288// Mapping from selectors to the methods that implement that selector, along
7289// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007290typedef llvm::DenseMap<Selector,
7291 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7292 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007293
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007294/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007295/// (and its superclasses, protocols, etc.) that meet the given
7296/// criteria. Insert those methods into the map of known methods,
7297/// indexed by selector so they can be easily found.
7298static void FindImplementableMethods(ASTContext &Context,
7299 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007300 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007301 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007302 KnownMethodsMap &KnownMethods,
7303 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007304 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007305 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007306 if (!IFace->hasDefinition())
7307 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007308
7309 IFace = IFace->getDefinition();
7310 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007311
Fangrui Song050229d2018-11-24 00:14:31 +00007312 const ObjCList<ObjCProtocolDecl> &Protocols =
7313 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007314 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007315 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007316 I != E; ++I)
7317 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007318 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007319
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007320 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007321 for (auto *Cat : IFace->visible_categories()) {
7322 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007323 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007324 }
7325
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007326 // Visit the superclass.
7327 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007328 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007329 WantInstanceMethods, ReturnType, KnownMethods,
7330 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007331 }
7332
7333 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7334 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007335 const ObjCList<ObjCProtocolDecl> &Protocols =
7336 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007337 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007338 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007339 I != E; ++I)
7340 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007341 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007342
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007343 // If this category is the original class, jump to the interface.
7344 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007345 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007346 WantInstanceMethods, ReturnType, KnownMethods,
7347 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007348 }
7349
7350 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007351 // Make sure we have a definition; that's what we'll walk.
7352 if (!Protocol->hasDefinition())
7353 return;
7354 Protocol = Protocol->getDefinition();
7355 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007356
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007357 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007358 const ObjCList<ObjCProtocolDecl> &Protocols =
7359 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007360 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007361 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007362 I != E; ++I)
7363 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7364 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007365 }
7366
7367 // Add methods in this container. This operation occurs last because
7368 // we want the methods from this container to override any methods
7369 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007370 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007371 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007372 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007373 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007374 continue;
7375
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007376 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007377 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007378 }
7379 }
7380}
7381
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007382/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007383/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007384static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007385 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007386 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007387 CodeCompletionBuilder &Builder) {
7388 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007389 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007390 if (!Quals.empty())
7391 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007392 Builder.AddTextChunk(
7393 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007394 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7395}
7396
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007397/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007398/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007399static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007400 if (!Class)
7401 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007402
Douglas Gregor669a25a2011-02-17 00:22:45 +00007403 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7404 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007405
Douglas Gregor669a25a2011-02-17 00:22:45 +00007406 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7407}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007408
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007409/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007410/// Key-Value Observing (KVO).
7411static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7412 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007413 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007414 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007415 ResultBuilder &Results) {
7416 IdentifierInfo *PropName = Property->getIdentifier();
7417 if (!PropName || PropName->getLength() == 0)
7418 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007419
Douglas Gregor75acd922011-09-27 23:30:47 +00007420 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7421
Douglas Gregor669a25a2011-02-17 00:22:45 +00007422 // Builder that will create each code completion.
7423 typedef CodeCompletionResult Result;
7424 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007425 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007426
Douglas Gregor669a25a2011-02-17 00:22:45 +00007427 // The selector table.
7428 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007429
Douglas Gregor669a25a2011-02-17 00:22:45 +00007430 // The property name, copied into the code completion allocation region
7431 // on demand.
7432 struct KeyHolder {
7433 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007434 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007435 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007436
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007437 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007438 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007439
Douglas Gregor669a25a2011-02-17 00:22:45 +00007440 operator const char *() {
7441 if (CopiedKey)
7442 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007443
Douglas Gregor669a25a2011-02-17 00:22:45 +00007444 return CopiedKey = Allocator.CopyString(Key);
7445 }
7446 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007447
Douglas Gregor669a25a2011-02-17 00:22:45 +00007448 // The uppercased name of the property name.
7449 std::string UpperKey = PropName->getName();
7450 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007451 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007452
Fangrui Song050229d2018-11-24 00:14:31 +00007453 bool ReturnTypeMatchesProperty =
7454 ReturnType.isNull() ||
7455 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7456 Property->getType());
7457 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007458
Douglas Gregor669a25a2011-02-17 00:22:45 +00007459 // Add the normal accessor -(type)key.
7460 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007461 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007462 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7463 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007464 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7465 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007466
Douglas Gregor669a25a2011-02-17 00:22:45 +00007467 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007468 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007469 CXCursor_ObjCInstanceMethodDecl));
7470 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007471
Douglas Gregor669a25a2011-02-17 00:22:45 +00007472 // If we have an integral or boolean property (or the user has provided
7473 // an integral or boolean return type), add the accessor -(type)isKey.
7474 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007475 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007476 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007477 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7478 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007479 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007480 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007481 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7482 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007483 if (ReturnType.isNull()) {
7484 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7485 Builder.AddTextChunk("BOOL");
7486 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7487 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007488
Fangrui Song050229d2018-11-24 00:14:31 +00007489 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007490 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007491 CXCursor_ObjCInstanceMethodDecl));
7492 }
7493 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007494
Douglas Gregor669a25a2011-02-17 00:22:45 +00007495 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007496 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007497 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007498 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007499 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007500 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007501 if (ReturnType.isNull()) {
7502 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7503 Builder.AddTextChunk("void");
7504 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7505 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007506
Fangrui Song050229d2018-11-24 00:14:31 +00007507 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007508 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007509 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7510 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007511 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007512 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007513 CXCursor_ObjCInstanceMethodDecl));
7514 }
7515 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007516
Douglas Gregor669a25a2011-02-17 00:22:45 +00007517 // Indexed and unordered accessors
7518 unsigned IndexedGetterPriority = CCP_CodePattern;
7519 unsigned IndexedSetterPriority = CCP_CodePattern;
7520 unsigned UnorderedGetterPriority = CCP_CodePattern;
7521 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007522 if (const auto *ObjCPointer =
7523 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007524 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7525 // If this interface type is not provably derived from a known
7526 // collection, penalize the corresponding completions.
7527 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007528 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007529 if (!InheritsFromClassNamed(IFace, "NSArray"))
7530 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7531 }
7532
7533 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007534 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007535 if (!InheritsFromClassNamed(IFace, "NSSet"))
7536 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7537 }
7538 }
7539 } else {
7540 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7541 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7542 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7543 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7544 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007545
Douglas Gregor669a25a2011-02-17 00:22:45 +00007546 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007547 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007548 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007549 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007550 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007551 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7552 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007553 if (ReturnType.isNull()) {
7554 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7555 Builder.AddTextChunk("NSUInteger");
7556 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7557 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007558
Fangrui Song050229d2018-11-24 00:14:31 +00007559 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7560 Results.AddResult(
7561 Result(Builder.TakeString(),
7562 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7563 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007564 }
7565 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007566
Douglas Gregor669a25a2011-02-17 00:22:45 +00007567 // Indexed getters
7568 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7569 if (IsInstanceMethod &&
7570 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007571 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007572 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007573 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007574 if (ReturnType.isNull()) {
7575 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7576 Builder.AddTextChunk("id");
7577 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7578 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007579
Douglas Gregor669a25a2011-02-17 00:22:45 +00007580 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7581 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7582 Builder.AddTextChunk("NSUInteger");
7583 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7584 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007585 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007586 CXCursor_ObjCInstanceMethodDecl));
7587 }
7588 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007589
Douglas Gregor669a25a2011-02-17 00:22:45 +00007590 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7591 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007592 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007593 (ReturnType->isObjCObjectPointerType() &&
7594 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007595 ReturnType->getAs<ObjCObjectPointerType>()
7596 ->getInterfaceDecl()
7597 ->getName() == "NSArray"))) {
7598 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007599 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007600 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007601 if (ReturnType.isNull()) {
7602 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7603 Builder.AddTextChunk("NSArray *");
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.AddTextChunk("NSIndexSet *");
7610 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7611 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007612 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007613 CXCursor_ObjCInstanceMethodDecl));
7614 }
7615 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007616
Douglas Gregor669a25a2011-02-17 00:22:45 +00007617 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7618 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007619 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007620 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7621 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007622
David Blaikie82e95a32014-11-19 07:49:47 +00007623 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007624 if (ReturnType.isNull()) {
7625 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7626 Builder.AddTextChunk("void");
7627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7628 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007629
Douglas Gregor669a25a2011-02-17 00:22:45 +00007630 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7631 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7632 Builder.AddPlaceholderChunk("object-type");
7633 Builder.AddTextChunk(" **");
7634 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7635 Builder.AddTextChunk("buffer");
7636 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7637 Builder.AddTypedTextChunk("range:");
7638 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7639 Builder.AddTextChunk("NSRange");
7640 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7641 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007642 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007643 CXCursor_ObjCInstanceMethodDecl));
7644 }
7645 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007646
Douglas Gregor669a25a2011-02-17 00:22:45 +00007647 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007648
Douglas Gregor669a25a2011-02-17 00:22:45 +00007649 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7650 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007651 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007652 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7653 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007654
David Blaikie82e95a32014-11-19 07:49:47 +00007655 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007656 if (ReturnType.isNull()) {
7657 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7658 Builder.AddTextChunk("void");
7659 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7660 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007661
Douglas Gregor669a25a2011-02-17 00:22:45 +00007662 Builder.AddTypedTextChunk("insertObject:");
7663 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7664 Builder.AddPlaceholderChunk("object-type");
7665 Builder.AddTextChunk(" *");
7666 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7667 Builder.AddTextChunk("object");
7668 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7669 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7670 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7671 Builder.AddPlaceholderChunk("NSUInteger");
7672 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7673 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007674 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007675 CXCursor_ObjCInstanceMethodDecl));
7676 }
7677 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007678
Douglas Gregor669a25a2011-02-17 00:22:45 +00007679 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7680 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007681 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007682 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7683 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007684
David Blaikie82e95a32014-11-19 07:49:47 +00007685 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007686 if (ReturnType.isNull()) {
7687 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7688 Builder.AddTextChunk("void");
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 Builder.AddTextChunk("NSArray *");
7695 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7696 Builder.AddTextChunk("array");
7697 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7698 Builder.AddTypedTextChunk("atIndexes:");
7699 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7700 Builder.AddPlaceholderChunk("NSIndexSet *");
7701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7702 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007703 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
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 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7709 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007710 std::string SelectorName =
7711 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007712 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007713 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007714 if (ReturnType.isNull()) {
7715 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7716 Builder.AddTextChunk("void");
7717 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7718 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007719
Douglas Gregor669a25a2011-02-17 00:22:45 +00007720 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7721 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7722 Builder.AddTextChunk("NSUInteger");
7723 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7724 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007725 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007726 CXCursor_ObjCInstanceMethodDecl));
7727 }
7728 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007729
Douglas Gregor669a25a2011-02-17 00:22:45 +00007730 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7731 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007732 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007733 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007734 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007735 if (ReturnType.isNull()) {
7736 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7737 Builder.AddTextChunk("void");
7738 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7739 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007740
Douglas Gregor669a25a2011-02-17 00:22:45 +00007741 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7742 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7743 Builder.AddTextChunk("NSIndexSet *");
7744 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7745 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007746 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007747 CXCursor_ObjCInstanceMethodDecl));
7748 }
7749 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007750
Douglas Gregor669a25a2011-02-17 00:22:45 +00007751 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7752 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007753 std::string SelectorName =
7754 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7755 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7756 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007757
David Blaikie82e95a32014-11-19 07:49:47 +00007758 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).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("NSUInteger");
7768 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7769 Builder.AddTextChunk("index");
7770 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7771 Builder.AddTypedTextChunk("withObject:");
7772 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7773 Builder.AddTextChunk("id");
7774 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7775 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007776 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007777 CXCursor_ObjCInstanceMethodDecl));
7778 }
7779 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007780
Douglas Gregor669a25a2011-02-17 00:22:45 +00007781 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7782 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007783 std::string SelectorName1 =
7784 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007785 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007786 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7787 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007788
David Blaikie82e95a32014-11-19 07:49:47 +00007789 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007790 if (ReturnType.isNull()) {
7791 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7792 Builder.AddTextChunk("void");
7793 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7794 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007795
Douglas Gregor669a25a2011-02-17 00:22:45 +00007796 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7797 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7798 Builder.AddPlaceholderChunk("NSIndexSet *");
7799 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7800 Builder.AddTextChunk("indexes");
7801 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7802 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7803 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7804 Builder.AddTextChunk("NSArray *");
7805 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7806 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007807 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007808 CXCursor_ObjCInstanceMethodDecl));
7809 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007810 }
7811
Douglas Gregor669a25a2011-02-17 00:22:45 +00007812 // Unordered getters
7813 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007814 if (IsInstanceMethod &&
7815 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007816 (ReturnType->isObjCObjectPointerType() &&
7817 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007818 ReturnType->getAs<ObjCObjectPointerType>()
7819 ->getInterfaceDecl()
7820 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007821 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007822 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007823 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7824 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007825 if (ReturnType.isNull()) {
7826 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7827 Builder.AddTextChunk("NSEnumerator *");
7828 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7829 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007830
Douglas Gregor669a25a2011-02-17 00:22:45 +00007831 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007832 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007833 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007834 }
7835 }
7836
7837 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007838 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007839 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007840 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007841 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007842 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007843 if (ReturnType.isNull()) {
7844 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7845 Builder.AddPlaceholderChunk("object-type");
7846 Builder.AddTextChunk(" *");
7847 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7848 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007849
Douglas Gregor669a25a2011-02-17 00:22:45 +00007850 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7852 if (ReturnType.isNull()) {
7853 Builder.AddPlaceholderChunk("object-type");
7854 Builder.AddTextChunk(" *");
7855 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007856 Builder.AddTextChunk(GetCompletionTypeString(
7857 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007858 }
7859 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7860 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007861 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007862 CXCursor_ObjCInstanceMethodDecl));
7863 }
7864 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007865
Douglas Gregor669a25a2011-02-17 00:22:45 +00007866 // Mutable unordered accessors
7867 // - (void)addKeyObject:(type *)object
7868 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007869 std::string SelectorName =
7870 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007871 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007872 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007873 if (ReturnType.isNull()) {
7874 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7875 Builder.AddTextChunk("void");
7876 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7877 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007878
Douglas Gregor669a25a2011-02-17 00:22:45 +00007879 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7880 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7881 Builder.AddPlaceholderChunk("object-type");
7882 Builder.AddTextChunk(" *");
7883 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7884 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007885 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007886 CXCursor_ObjCInstanceMethodDecl));
7887 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007888 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007889
7890 // - (void)addKey:(NSSet *)objects
7891 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007892 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007893 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007894 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007895 if (ReturnType.isNull()) {
7896 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7897 Builder.AddTextChunk("void");
7898 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7899 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007900
Douglas Gregor669a25a2011-02-17 00:22:45 +00007901 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7902 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7903 Builder.AddTextChunk("NSSet *");
7904 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7905 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007906 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007907 CXCursor_ObjCInstanceMethodDecl));
7908 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007909 }
7910
Douglas Gregor669a25a2011-02-17 00:22:45 +00007911 // - (void)removeKeyObject:(type *)object
7912 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007913 std::string SelectorName =
7914 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007915 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007916 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007917 if (ReturnType.isNull()) {
7918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7919 Builder.AddTextChunk("void");
7920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7921 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007922
Douglas Gregor669a25a2011-02-17 00:22:45 +00007923 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7924 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7925 Builder.AddPlaceholderChunk("object-type");
7926 Builder.AddTextChunk(" *");
7927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7928 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007929 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007930 CXCursor_ObjCInstanceMethodDecl));
7931 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007932 }
7933
Douglas Gregor669a25a2011-02-17 00:22:45 +00007934 // - (void)removeKey:(NSSet *)objects
7935 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007936 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007937 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007938 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007939 if (ReturnType.isNull()) {
7940 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7941 Builder.AddTextChunk("void");
7942 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7943 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007944
Douglas Gregor669a25a2011-02-17 00:22:45 +00007945 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7946 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7947 Builder.AddTextChunk("NSSet *");
7948 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7949 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007950 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007951 CXCursor_ObjCInstanceMethodDecl));
7952 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007953 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007954
7955 // - (void)intersectKey:(NSSet *)objects
7956 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007957 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007958 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007959 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007960 if (ReturnType.isNull()) {
7961 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7962 Builder.AddTextChunk("void");
7963 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7964 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007965
Douglas Gregor669a25a2011-02-17 00:22:45 +00007966 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7967 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7968 Builder.AddTextChunk("NSSet *");
7969 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7970 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007971 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007972 CXCursor_ObjCInstanceMethodDecl));
7973 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007974 }
7975
Douglas Gregor669a25a2011-02-17 00:22:45 +00007976 // Key-Value Observing
7977 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007978 if (!IsInstanceMethod &&
7979 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007980 (ReturnType->isObjCObjectPointerType() &&
7981 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007982 ReturnType->getAs<ObjCObjectPointerType>()
7983 ->getInterfaceDecl()
7984 ->getName() == "NSSet"))) {
7985 std::string SelectorName =
7986 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007987 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007988 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7989 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007990 if (ReturnType.isNull()) {
7991 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007992 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7994 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007995
Douglas Gregor669a25a2011-02-17 00:22:45 +00007996 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007997 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007998 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00007999 }
8000 }
8001
8002 // + (BOOL)automaticallyNotifiesObserversForKey
8003 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00008004 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00008005 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00008006 std::string SelectorName =
8007 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00008008 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008009 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8010 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00008011 if (ReturnType.isNull()) {
8012 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8013 Builder.AddTextChunk("BOOL");
8014 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8015 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008016
Douglas Gregor857bcda2011-06-02 04:02:27 +00008017 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008018 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008019 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008020 }
8021 }
8022}
8023
Alex Lorenzb8740422017-10-24 16:39:37 +00008024void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008025 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008026 // Determine the return type of the method we're declaring, if
8027 // provided.
8028 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00008029 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008030 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00008031 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
8032 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008033 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008034 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00008035 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00008036 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00008037 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008038 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
8039 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008040 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00008041 } else if (ObjCCategoryImplDecl *CatImpl =
8042 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008043 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008044 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008045 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00008046 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008047 }
8048
8049 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00008050 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00008051 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008052 }
8053
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008054 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008055 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008056 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008057 return;
8058 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008059
Douglas Gregor636a61e2010-04-07 00:21:17 +00008060 // Find all of the methods that we could declare/implement here.
8061 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00008062 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
8063 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008064
Douglas Gregor636a61e2010-04-07 00:21:17 +00008065 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00008066 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008067 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008068 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008069 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008070 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00008071 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008072 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008073 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008074 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008075 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008076 CodeCompletionBuilder Builder(Results.getAllocator(),
8077 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00008078
8079 // Add the '-'/'+' prefix if it wasn't provided yet.
8080 if (!IsInstanceMethod) {
8081 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
8082 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8083 }
8084
Douglas Gregor636a61e2010-04-07 00:21:17 +00008085 // If the result type was not already provided, add it to the
8086 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008087 if (ReturnType.isNull()) {
8088 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
8089 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00008090 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
8091 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008092 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008093
8094 Selector Sel = Method->getSelector();
8095
8096 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00008097 Builder.AddTypedTextChunk(
8098 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008099
8100 // Add parameters to the pattern.
8101 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008102 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008103 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008104 P != PEnd; (void)++P, ++I) {
8105 // Add the part of the selector name.
8106 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008107 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00008108 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008109 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8110 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00008111 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008112 } else
8113 break;
8114
8115 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00008116 QualType ParamType;
8117 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
8118 ParamType = (*P)->getType();
8119 else
8120 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00008121 ParamType = ParamType.substObjCTypeArgs(
8122 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008123 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00008124 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
8125 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008126
Douglas Gregor636a61e2010-04-07 00:21:17 +00008127 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00008128 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008129 }
8130
8131 if (Method->isVariadic()) {
8132 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008133 Builder.AddChunk(CodeCompletionString::CK_Comma);
8134 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008135 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008136
Douglas Gregord37c59d2010-05-28 00:57:46 +00008137 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008138 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008139 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8140 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8141 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008142 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008143 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008144 Builder.AddTextChunk("return");
8145 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8146 Builder.AddPlaceholderChunk("expression");
8147 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008148 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008149 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008150
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008151 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8152 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008153 }
8154
Douglas Gregor416b5752010-08-25 01:08:01 +00008155 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008156 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008157 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008158 setInBaseClass(R);
8159 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008160 }
8161
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008162 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008163 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008164 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008165 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008166 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008167
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008168 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008169 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008170 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008171 M != MEnd; ++M)
8172 KnownSelectors.insert(M->first);
8173
Douglas Gregor669a25a2011-02-17 00:22:45 +00008174 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8175 if (!IFace)
8176 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8177 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008178
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008179 if (IFace)
8180 for (auto *Cat : IFace->visible_categories())
8181 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008182
8183 if (IsInstanceMethod) {
8184 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8185 for (auto *P : Containers[I]->instance_properties())
8186 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8187 KnownSelectors, Results);
8188 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008189 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008190
Douglas Gregor636a61e2010-04-07 00:21:17 +00008191 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008192
8193 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8194 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008195}
Douglas Gregor95887f92010-07-08 23:20:03 +00008196
Fangrui Song050229d2018-11-24 00:14:31 +00008197void Sema::CodeCompleteObjCMethodDeclSelector(
8198 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8199 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008200 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008201 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008202 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008203 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8204 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008205 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008206 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008207 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008208
8209 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008210 }
8211 }
8212
8213 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008214 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008215 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008216 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008217 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008218
Douglas Gregor95887f92010-07-08 23:20:03 +00008219 if (ReturnTy)
8220 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008221
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008222 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008223 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8224 MEnd = MethodPool.end();
8225 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008226 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8227 : &M->second.second;
8228 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008229 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008230 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008231
Douglas Gregor45879692010-07-08 23:37:41 +00008232 if (AtParameterName) {
8233 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008234 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008235 if (NumSelIdents &&
8236 NumSelIdents <= MethList->getMethod()->param_size()) {
8237 ParmVarDecl *Param =
8238 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008239 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008240 CodeCompletionBuilder Builder(Results.getAllocator(),
8241 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008242 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008243 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008244 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008245 }
8246 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008247
Douglas Gregor45879692010-07-08 23:37:41 +00008248 continue;
8249 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008250
Nico Weber2e0c8f72014-12-27 03:58:08 +00008251 Result R(MethList->getMethod(),
8252 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008253 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008254 R.AllParametersAreInformative = false;
8255 R.DeclaringEntity = true;
8256 Results.MaybeAddResult(R, CurContext);
8257 }
8258 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008259
Douglas Gregor95887f92010-07-08 23:20:03 +00008260 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008261
8262 if (!AtParameterName && !SelIdents.empty() &&
8263 SelIdents.front()->getName().startswith("init")) {
8264 for (const auto &M : PP.macros()) {
8265 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8266 continue;
8267 Results.EnterNewScope();
8268 CodeCompletionBuilder Builder(Results.getAllocator(),
8269 Results.getCodeCompletionTUInfo());
8270 Builder.AddTypedTextChunk(
8271 Builder.getAllocator().CopyString(M.first->getName()));
8272 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8273 CXCursor_MacroDefinition));
8274 Results.ExitScope();
8275 }
8276 }
8277
Eric Liuf5ba09f2018-07-04 10:01:18 +00008278 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8279 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008280}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008281
Douglas Gregorec00a262010-08-24 22:20:20 +00008282void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008283 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008284 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008285 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008286 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008287
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008288 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008289 CodeCompletionBuilder Builder(Results.getAllocator(),
8290 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008291 Builder.AddTypedTextChunk("if");
8292 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8293 Builder.AddPlaceholderChunk("condition");
8294 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008295
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008296 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008297 Builder.AddTypedTextChunk("ifdef");
8298 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8299 Builder.AddPlaceholderChunk("macro");
8300 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008301
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008302 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008303 Builder.AddTypedTextChunk("ifndef");
8304 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8305 Builder.AddPlaceholderChunk("macro");
8306 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008307
8308 if (InConditional) {
8309 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008310 Builder.AddTypedTextChunk("elif");
8311 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8312 Builder.AddPlaceholderChunk("condition");
8313 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008314
8315 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008316 Builder.AddTypedTextChunk("else");
8317 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008318
8319 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008320 Builder.AddTypedTextChunk("endif");
8321 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008322 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008323
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008324 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008325 Builder.AddTypedTextChunk("include");
8326 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8327 Builder.AddTextChunk("\"");
8328 Builder.AddPlaceholderChunk("header");
8329 Builder.AddTextChunk("\"");
8330 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008331
8332 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008333 Builder.AddTypedTextChunk("include");
8334 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8335 Builder.AddTextChunk("<");
8336 Builder.AddPlaceholderChunk("header");
8337 Builder.AddTextChunk(">");
8338 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008339
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008340 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008341 Builder.AddTypedTextChunk("define");
8342 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8343 Builder.AddPlaceholderChunk("macro");
8344 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008345
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008346 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008347 Builder.AddTypedTextChunk("define");
8348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8349 Builder.AddPlaceholderChunk("macro");
8350 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8351 Builder.AddPlaceholderChunk("args");
8352 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8353 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008354
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008355 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008356 Builder.AddTypedTextChunk("undef");
8357 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8358 Builder.AddPlaceholderChunk("macro");
8359 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008360
8361 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008362 Builder.AddTypedTextChunk("line");
8363 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8364 Builder.AddPlaceholderChunk("number");
8365 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008366
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008367 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008368 Builder.AddTypedTextChunk("line");
8369 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8370 Builder.AddPlaceholderChunk("number");
8371 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8372 Builder.AddTextChunk("\"");
8373 Builder.AddPlaceholderChunk("filename");
8374 Builder.AddTextChunk("\"");
8375 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008376
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008377 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008378 Builder.AddTypedTextChunk("error");
8379 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8380 Builder.AddPlaceholderChunk("message");
8381 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008382
8383 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008384 Builder.AddTypedTextChunk("pragma");
8385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8386 Builder.AddPlaceholderChunk("arguments");
8387 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008388
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008389 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008390 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008391 Builder.AddTypedTextChunk("import");
8392 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8393 Builder.AddTextChunk("\"");
8394 Builder.AddPlaceholderChunk("header");
8395 Builder.AddTextChunk("\"");
8396 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008397
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008398 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008399 Builder.AddTypedTextChunk("import");
8400 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8401 Builder.AddTextChunk("<");
8402 Builder.AddPlaceholderChunk("header");
8403 Builder.AddTextChunk(">");
8404 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008405 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008406
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008407 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008408 Builder.AddTypedTextChunk("include_next");
8409 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8410 Builder.AddTextChunk("\"");
8411 Builder.AddPlaceholderChunk("header");
8412 Builder.AddTextChunk("\"");
8413 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008414
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008415 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008416 Builder.AddTypedTextChunk("include_next");
8417 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8418 Builder.AddTextChunk("<");
8419 Builder.AddPlaceholderChunk("header");
8420 Builder.AddTextChunk(">");
8421 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008422
8423 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008424 Builder.AddTypedTextChunk("warning");
8425 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8426 Builder.AddPlaceholderChunk("message");
8427 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008428
8429 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8430 // completions for them. And __include_macros is a Clang-internal extension
8431 // that we don't want to encourage anyone to use.
8432
8433 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8434 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008435
8436 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008437 Results.data(), Results.size());
8438}
8439
8440void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008441 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8442 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008443}
8444
Douglas Gregorec00a262010-08-24 22:20:20 +00008445void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008446 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008447 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008448 IsDefinition ? CodeCompletionContext::CCC_MacroName
8449 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008450 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008451 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008452 CodeCompletionBuilder Builder(Results.getAllocator(),
8453 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008454 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008455 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008456 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008457 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008458 Builder.AddTypedTextChunk(
8459 Builder.getAllocator().CopyString(M->first->getName()));
8460 Results.AddResult(CodeCompletionResult(
8461 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008462 }
8463 Results.ExitScope();
8464 } else if (IsDefinition) {
8465 // FIXME: Can we detect when the user just wrote an include guard above?
8466 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008467
Douglas Gregor0ac41382010-09-23 23:01:17 +00008468 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008469 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008470}
8471
Douglas Gregorec00a262010-08-24 22:20:20 +00008472void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008473 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008474 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008475 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008476
Douglas Gregorec00a262010-08-24 22:20:20 +00008477 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008478 AddMacroResults(PP, Results,
8479 CodeCompleter ? CodeCompleter->loadExternal() : false,
8480 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008481
Fangrui Song050229d2018-11-24 00:14:31 +00008482 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008483 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008484 CodeCompletionBuilder Builder(Results.getAllocator(),
8485 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008486 Builder.AddTypedTextChunk("defined");
8487 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8488 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8489 Builder.AddPlaceholderChunk("macro");
8490 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8491 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008492 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008493
8494 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8495 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008496}
8497
8498void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8499 IdentifierInfo *Macro,
8500 MacroInfo *MacroInfo,
8501 unsigned Argument) {
8502 // FIXME: In the future, we could provide "overload" results, much like we
8503 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008504
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008505 // Now just ignore this. There will be another code-completion callback
8506 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008507}
8508
Sam McCall3d8051a2018-09-18 08:40:41 +00008509// This handles completion inside an #include filename, e.g. #include <foo/ba
8510// We look for the directory "foo" under each directory on the include path,
8511// list its files, and reassemble the appropriate #include.
8512void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8513 // RelDir should use /, but unescaped \ is possible on windows!
8514 // Our completions will normalize to / for simplicity, this case is rare.
8515 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8516 // We need the native slashes for the actual file system interactions.
8517 SmallString<128> NativeRelDir = StringRef(RelDir);
8518 llvm::sys::path::native(NativeRelDir);
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008519 llvm::vfs::FileSystem &FS =
8520 getSourceManager().getFileManager().getVirtualFileSystem();
Sam McCall3d8051a2018-09-18 08:40:41 +00008521
8522 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8523 CodeCompleter->getCodeCompletionTUInfo(),
8524 CodeCompletionContext::CCC_IncludedFile);
8525 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8526
8527 // Helper: adds one file or directory completion result.
8528 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8529 SmallString<64> TypedChunk = Filename;
8530 // Directory completion is up to the slash, e.g. <sys/
8531 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8532 auto R = SeenResults.insert(TypedChunk);
8533 if (R.second) { // New completion
8534 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8535 *R.first = InternedTyped; // Avoid dangling StringRef.
8536 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8537 CodeCompleter->getCodeCompletionTUInfo());
8538 Builder.AddTypedTextChunk(InternedTyped);
8539 // The result is a "Pattern", which is pretty opaque.
8540 // We may want to include the real filename to allow smart ranking.
8541 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8542 }
8543 };
8544
8545 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008546 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8547 bool IsSystem,
8548 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008549 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008550 if (!NativeRelDir.empty()) {
8551 if (LookupType == DirectoryLookup::LT_Framework) {
8552 // For a framework dir, #include <Foo/Bar/> actually maps to
8553 // a path of Foo.framework/Headers/Bar/.
8554 auto Begin = llvm::sys::path::begin(NativeRelDir);
8555 auto End = llvm::sys::path::end(NativeRelDir);
8556
8557 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8558 llvm::sys::path::append(Dir, ++Begin, End);
8559 } else {
8560 llvm::sys::path::append(Dir, NativeRelDir);
8561 }
8562 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008563
8564 std::error_code EC;
8565 unsigned Count = 0;
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008566 for (auto It = FS.dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008567 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008568 if (++Count == 2500) // If we happen to hit a huge directory,
8569 break; // bail out early so we're not too slow.
8570 StringRef Filename = llvm::sys::path::filename(It->path());
8571 switch (It->type()) {
8572 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008573 // All entries in a framework directory must have a ".framework" suffix,
8574 // but the suffix does not appear in the source code's include/import.
8575 if (LookupType == DirectoryLookup::LT_Framework &&
8576 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8577 break;
8578
Sam McCall3d8051a2018-09-18 08:40:41 +00008579 AddCompletion(Filename, /*IsDirectory=*/true);
8580 break;
8581 case llvm::sys::fs::file_type::regular_file:
8582 // Only files that really look like headers. (Except in system dirs).
8583 if (!IsSystem) {
8584 // Header extensions from Types.def, which we can't depend on here.
8585 if (!(Filename.endswith_lower(".h") ||
8586 Filename.endswith_lower(".hh") ||
8587 Filename.endswith_lower(".hpp") ||
8588 Filename.endswith_lower(".inc")))
8589 break;
8590 }
8591 AddCompletion(Filename, /*IsDirectory=*/false);
8592 break;
8593 default:
8594 break;
8595 }
8596 }
8597 };
8598
8599 // Helper: adds results relative to IncludeDir, if possible.
8600 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8601 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008602 switch (IncludeDir.getLookupType()) {
8603 case DirectoryLookup::LT_HeaderMap:
8604 // header maps are not (currently) enumerable.
8605 break;
8606 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008607 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8608 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008609 break;
8610 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008611 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8612 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008613 break;
8614 }
8615 };
8616
8617 // Finally with all our helpers, we can scan the include path.
8618 // Do this in standard order so deduplication keeps the right file.
8619 // (In case we decide to add more details to the results later).
8620 const auto &S = PP.getHeaderSearchInfo();
8621 using llvm::make_range;
8622 if (!Angled) {
8623 // The current directory is on the include path for "quoted" includes.
8624 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8625 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008626 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8627 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008628 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8629 AddFilesFromDirLookup(D, false);
8630 }
8631 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008632 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008633 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8634 AddFilesFromDirLookup(D, true);
8635
8636 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8637 Results.data(), Results.size());
8638}
8639
Douglas Gregor11583702010-08-25 17:04:25 +00008640void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008641 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008642 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8643 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008644}
8645
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008646void Sema::CodeCompleteAvailabilityPlatformName() {
8647 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8648 CodeCompleter->getCodeCompletionTUInfo(),
8649 CodeCompletionContext::CCC_Other);
8650 Results.EnterNewScope();
8651 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8652 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8653 Results.AddResult(CodeCompletionResult(Platform));
8654 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8655 Twine(Platform) + "ApplicationExtension")));
8656 }
8657 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008658 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8659 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008660}
8661
Fangrui Song050229d2018-11-24 00:14:31 +00008662void Sema::GatherGlobalCodeCompletions(
8663 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8664 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008665 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8666 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008667 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008668 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008669 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008670 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8671 Consumer,
8672 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008673 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008674
Douglas Gregorb14904c2010-08-13 22:48:40 +00008675 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008676 AddMacroResults(PP, Builder,
8677 CodeCompleter ? CodeCompleter->loadExternal() : false,
8678 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008679
Douglas Gregorb14904c2010-08-13 22:48:40 +00008680 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008681 Results.insert(Results.end(), Builder.data(),
8682 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008683}