blob: 0946a24676dc9d2c62ffc11539b8c1f415860680 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Douglas Gregor2436e712009-09-17 21:32:03 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the code-completion semantic actions.
10//
11//===----------------------------------------------------------------------===//
Eric Liub91e0812018-10-02 10:29:00 +000012#include "clang/AST/Decl.h"
Ilya Biryukov98397552018-12-05 17:38:39 +000013#include "clang/AST/DeclBase.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000014#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000015#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000016#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000017#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000018#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000019#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000020#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000021#include "clang/Lex/MacroInfo.h"
22#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Overload.h"
26#include "clang/Sema/Scope.h"
27#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000028#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000029#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000030#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000031#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000032#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000033#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000034#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000035#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000036#include "llvm/ADT/iterator_range.h"
37#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000038#include <list>
39#include <map>
40#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000041
42using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000043using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000044
Douglas Gregor3545ff42009-09-21 16:56:56 +000045namespace {
Fangrui Song050229d2018-11-24 00:14:31 +000046/// A container of code-completion results.
47class ResultBuilder {
48public:
49 /// The type of a name-lookup filter, which can be provided to the
50 /// name-lookup routines to specify which declarations should be included in
51 /// the result set (when it returns true) and which declarations should be
52 /// filtered out (returns false).
53 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000054
Fangrui Song050229d2018-11-24 00:14:31 +000055 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000056
Fangrui Song050229d2018-11-24 00:14:31 +000057private:
58 /// The actual results we have found.
59 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000060
Fangrui Song050229d2018-11-24 00:14:31 +000061 /// A record of all of the declarations we have found and placed
62 /// into the result set, used to ensure that no declaration ever gets into
63 /// the result set twice.
64 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000065
Fangrui Song050229d2018-11-24 00:14:31 +000066 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000067
Fangrui Song050229d2018-11-24 00:14:31 +000068 /// An entry in the shadow map, which is optimized to store
69 /// a single (declaration, index) mapping (the common case) but
70 /// can also store a list of (declaration, index) mappings.
71 class ShadowMapEntry {
72 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000073
Fangrui Song050229d2018-11-24 00:14:31 +000074 /// Contains either the solitary NamedDecl * or a vector
75 /// of (declaration, index) pairs.
76 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000077
Fangrui Song050229d2018-11-24 00:14:31 +000078 /// When the entry contains a single declaration, this is
79 /// the index associated with that entry.
80 unsigned SingleDeclIndex;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000081
Douglas Gregor3545ff42009-09-21 16:56:56 +000082 public:
Fangrui Song050229d2018-11-24 00:14:31 +000083 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000084
Fangrui Song050229d2018-11-24 00:14:31 +000085 void Add(const NamedDecl *ND, unsigned Index) {
86 if (DeclOrVector.isNull()) {
87 // 0 - > 1 elements: just set the single element information.
88 DeclOrVector = ND;
89 SingleDeclIndex = Index;
90 return;
91 }
92
93 if (const NamedDecl *PrevND =
94 DeclOrVector.dyn_cast<const NamedDecl *>()) {
95 // 1 -> 2 elements: create the vector of results and push in the
96 // existing declaration.
97 DeclIndexPairVector *Vec = new DeclIndexPairVector;
98 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
99 DeclOrVector = Vec;
100 }
101
102 // Add the new element to the end of the vector.
103 DeclOrVector.get<DeclIndexPairVector *>()->push_back(
104 DeclIndexPair(ND, Index));
105 }
106
107 void Destroy() {
108 if (DeclIndexPairVector *Vec =
109 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
110 delete Vec;
111 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05fcf842010-11-02 20:36:02 +0000112 }
113 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000114
Fangrui Song050229d2018-11-24 00:14:31 +0000115 // Iteration.
116 class iterator;
117 iterator begin() const;
118 iterator end() const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000119 };
Fangrui Song050229d2018-11-24 00:14:31 +0000120
121 /// A mapping from declaration names to the declarations that have
122 /// this name within a particular scope and their index within the list of
123 /// results.
124 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
125
126 /// The semantic analysis object for which results are being
127 /// produced.
128 Sema &SemaRef;
129
130 /// The allocator used to allocate new code-completion strings.
131 CodeCompletionAllocator &Allocator;
132
133 CodeCompletionTUInfo &CCTUInfo;
134
135 /// If non-NULL, a filter function used to remove any code-completion
136 /// results that are not desirable.
137 LookupFilter Filter;
138
139 /// Whether we should allow declarations as
140 /// nested-name-specifiers that would otherwise be filtered out.
141 bool AllowNestedNameSpecifiers;
142
143 /// If set, the type that we would prefer our resulting value
144 /// declarations to have.
145 ///
146 /// Closely matching the preferred type gives a boost to a result's
147 /// priority.
148 CanQualType PreferredType;
149
150 /// A list of shadow maps, which is used to model name hiding at
151 /// different levels of, e.g., the inheritance hierarchy.
152 std::list<ShadowMap> ShadowMaps;
153
154 /// If we're potentially referring to a C++ member function, the set
155 /// of qualifiers applied to the object type.
156 Qualifiers ObjectTypeQualifiers;
157
158 /// Whether the \p ObjectTypeQualifiers field is active.
159 bool HasObjectTypeQualifiers;
160
161 /// The selector that we prefer.
162 Selector PreferredSelector;
163
164 /// The completion context in which we are gathering results.
165 CodeCompletionContext CompletionContext;
166
167 /// If we are in an instance method definition, the \@implementation
168 /// object.
169 ObjCImplementationDecl *ObjCImplementation;
170
171 void AdjustResultPriorityForDecl(Result &R);
172
173 void MaybeAddConstructorResults(Result R);
174
175public:
176 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
177 CodeCompletionTUInfo &CCTUInfo,
178 const CodeCompletionContext &CompletionContext,
179 LookupFilter Filter = nullptr)
180 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
181 Filter(Filter), AllowNestedNameSpecifiers(false),
182 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
183 ObjCImplementation(nullptr) {
184 // If this is an Objective-C instance method definition, dig out the
185 // corresponding implementation.
186 switch (CompletionContext.getKind()) {
187 case CodeCompletionContext::CCC_Expression:
188 case CodeCompletionContext::CCC_ObjCMessageReceiver:
189 case CodeCompletionContext::CCC_ParenthesizedExpression:
190 case CodeCompletionContext::CCC_Statement:
191 case CodeCompletionContext::CCC_Recovery:
192 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
193 if (Method->isInstanceMethod())
194 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
195 ObjCImplementation = Interface->getImplementation();
196 break;
197
198 default:
199 break;
200 }
201 }
202
203 /// Determine the priority for a reference to the given declaration.
204 unsigned getBasePriority(const NamedDecl *D);
205
206 /// Whether we should include code patterns in the completion
207 /// results.
208 bool includeCodePatterns() const {
209 return SemaRef.CodeCompleter &&
210 SemaRef.CodeCompleter->includeCodePatterns();
211 }
212
213 /// Set the filter used for code-completion results.
214 void setFilter(LookupFilter Filter) { this->Filter = Filter; }
215
216 Result *data() { return Results.empty() ? nullptr : &Results.front(); }
217 unsigned size() const { return Results.size(); }
218 bool empty() const { return Results.empty(); }
219
220 /// Specify the preferred type.
221 void setPreferredType(QualType T) {
222 PreferredType = SemaRef.Context.getCanonicalType(T);
223 }
224
225 /// Set the cv-qualifiers on the object type, for us in filtering
226 /// calls to member functions.
227 ///
228 /// When there are qualifiers in this set, they will be used to filter
229 /// out member functions that aren't available (because there will be a
230 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
231 /// match.
232 void setObjectTypeQualifiers(Qualifiers Quals) {
233 ObjectTypeQualifiers = Quals;
234 HasObjectTypeQualifiers = true;
235 }
236
237 /// Set the preferred selector.
238 ///
239 /// When an Objective-C method declaration result is added, and that
240 /// method's selector matches this preferred selector, we give that method
241 /// a slight priority boost.
242 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
243
244 /// Retrieve the code-completion context for which results are
245 /// being collected.
246 const CodeCompletionContext &getCompletionContext() const {
247 return CompletionContext;
248 }
249
250 /// Specify whether nested-name-specifiers are allowed.
251 void allowNestedNameSpecifiers(bool Allow = true) {
252 AllowNestedNameSpecifiers = Allow;
253 }
254
255 /// Return the semantic analysis object for which we are collecting
256 /// code completion results.
257 Sema &getSema() const { return SemaRef; }
258
259 /// Retrieve the allocator used to allocate code completion strings.
260 CodeCompletionAllocator &getAllocator() const { return Allocator; }
261
262 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
263
264 /// Determine whether the given declaration is at all interesting
265 /// as a code-completion result.
266 ///
267 /// \param ND the declaration that we are inspecting.
268 ///
269 /// \param AsNestedNameSpecifier will be set true if this declaration is
270 /// only interesting when it is a nested-name-specifier.
271 bool isInterestingDecl(const NamedDecl *ND,
272 bool &AsNestedNameSpecifier) const;
273
274 /// Check whether the result is hidden by the Hiding declaration.
275 ///
276 /// \returns true if the result is hidden and cannot be found, false if
277 /// the hidden result could still be found. When false, \p R may be
278 /// modified to describe how the result can be found (e.g., via extra
279 /// qualification).
280 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
281 const NamedDecl *Hiding);
282
283 /// Add a new result to this result set (if it isn't already in one
284 /// of the shadow maps), or replace an existing result (for, e.g., a
285 /// redeclaration).
286 ///
287 /// \param R the result to add (if it is unique).
288 ///
289 /// \param CurContext the context in which this result will be named.
290 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
291
292 /// Add a new result to this result set, where we already know
293 /// the hiding declaration (if any).
294 ///
295 /// \param R the result to add (if it is unique).
296 ///
297 /// \param CurContext the context in which this result will be named.
298 ///
299 /// \param Hiding the declaration that hides the result.
300 ///
301 /// \param InBaseClass whether the result was found in a base
302 /// class of the searched context.
303 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
304 bool InBaseClass);
305
306 /// Add a new non-declaration result to this result set.
307 void AddResult(Result R);
308
309 /// Enter into a new scope.
310 void EnterNewScope();
311
312 /// Exit from the current scope.
313 void ExitScope();
314
315 /// Ignore this declaration, if it is seen again.
316 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
317
318 /// Add a visited context.
319 void addVisitedContext(DeclContext *Ctx) {
320 CompletionContext.addVisitedContext(Ctx);
321 }
322
323 /// \name Name lookup predicates
324 ///
325 /// These predicates can be passed to the name lookup functions to filter the
326 /// results of name lookup. All of the predicates have the same type, so that
327 ///
328 //@{
329 bool IsOrdinaryName(const NamedDecl *ND) const;
330 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
331 bool IsIntegralConstantValue(const NamedDecl *ND) const;
332 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
333 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
334 bool IsEnum(const NamedDecl *ND) const;
335 bool IsClassOrStruct(const NamedDecl *ND) const;
336 bool IsUnion(const NamedDecl *ND) const;
337 bool IsNamespace(const NamedDecl *ND) const;
338 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
339 bool IsType(const NamedDecl *ND) const;
340 bool IsMember(const NamedDecl *ND) const;
341 bool IsObjCIvar(const NamedDecl *ND) const;
342 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
343 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
344 bool IsObjCCollection(const NamedDecl *ND) const;
345 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
346 //@}
347};
348} // namespace
Douglas Gregor3545ff42009-09-21 16:56:56 +0000349
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000350void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
351 if (isa<BlockDecl>(S.CurContext)) {
352 if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000353 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000354 Type = BSI->ReturnType;
355 ExpectedLoc = Tok;
356 }
357 } else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000358 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000359 Type = Function->getReturnType();
360 ExpectedLoc = Tok;
361 } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000362 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000363 Type = Method->getReturnType();
364 ExpectedLoc = Tok;
365 }
366}
367
368void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {
369 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000370 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000371 Type = VD ? VD->getType() : QualType();
372 ExpectedLoc = Tok;
373}
374
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000375void PreferredTypeBuilder::enterFunctionArgument(
376 SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) {
377 this->ComputeType = ComputeType;
378 Type = QualType();
379 ExpectedLoc = Tok;
380}
381
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000382void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,
383 SourceLocation LParLoc) {
384 // expected type for parenthesized expression does not change.
385 if (ExpectedLoc == LParLoc)
386 ExpectedLoc = Tok;
387}
388
389static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
390 tok::TokenKind Op) {
391 if (!LHS)
392 return QualType();
393
394 QualType LHSType = LHS->getType();
395 if (LHSType->isPointerType()) {
396 if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
397 return S.getASTContext().getPointerDiffType();
398 // Pointer difference is more common than subtracting an int from a pointer.
399 if (Op == tok::minus)
400 return LHSType;
401 }
402
403 switch (Op) {
404 // No way to infer the type of RHS from LHS.
405 case tok::comma:
406 return QualType();
407 // Prefer the type of the left operand for all of these.
408 // Arithmetic operations.
409 case tok::plus:
410 case tok::plusequal:
411 case tok::minus:
412 case tok::minusequal:
413 case tok::percent:
414 case tok::percentequal:
415 case tok::slash:
416 case tok::slashequal:
417 case tok::star:
418 case tok::starequal:
419 // Assignment.
420 case tok::equal:
421 // Comparison operators.
422 case tok::equalequal:
423 case tok::exclaimequal:
424 case tok::less:
425 case tok::lessequal:
426 case tok::greater:
427 case tok::greaterequal:
428 case tok::spaceship:
429 return LHS->getType();
430 // Binary shifts are often overloaded, so don't try to guess those.
431 case tok::greatergreater:
432 case tok::greatergreaterequal:
433 case tok::lessless:
434 case tok::lesslessequal:
435 if (LHSType->isIntegralOrEnumerationType())
436 return S.getASTContext().IntTy;
437 return QualType();
438 // Logical operators, assume we want bool.
439 case tok::ampamp:
440 case tok::pipepipe:
441 case tok::caretcaret:
442 return S.getASTContext().BoolTy;
443 // Operators often used for bit manipulation are typically used with the type
444 // of the left argument.
445 case tok::pipe:
446 case tok::pipeequal:
447 case tok::caret:
448 case tok::caretequal:
449 case tok::amp:
450 case tok::ampequal:
451 if (LHSType->isIntegralOrEnumerationType())
452 return LHSType;
453 return QualType();
454 // RHS should be a pointer to a member of the 'LHS' type, but we can't give
455 // any particular type here.
456 case tok::periodstar:
457 case tok::arrowstar:
458 return QualType();
459 default:
460 // FIXME(ibiryukov): handle the missing op, re-add the assertion.
461 // assert(false && "unhandled binary op");
462 return QualType();
463 }
464}
465
466/// Get preferred type for an argument of an unary expression. \p ContextType is
467/// preferred type of the whole unary expression.
468static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType,
469 tok::TokenKind Op) {
470 switch (Op) {
471 case tok::exclaim:
472 return S.getASTContext().BoolTy;
473 case tok::amp:
474 if (!ContextType.isNull() && ContextType->isPointerType())
475 return ContextType->getPointeeType();
476 return QualType();
477 case tok::star:
478 if (ContextType.isNull())
479 return QualType();
480 return S.getASTContext().getPointerType(ContextType.getNonReferenceType());
481 case tok::plus:
482 case tok::minus:
483 case tok::tilde:
484 case tok::minusminus:
485 case tok::plusplus:
486 if (ContextType.isNull())
487 return S.getASTContext().IntTy;
488 // leave as is, these operators typically return the same type.
489 return ContextType;
490 case tok::kw___real:
491 case tok::kw___imag:
492 return QualType();
493 default:
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000494 assert(false && "unhandled unary op");
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000495 return QualType();
496 }
497}
498
499void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,
500 tok::TokenKind Op) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000501 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000502 Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);
503 ExpectedLoc = Tok;
504}
505
506void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok,
507 Expr *Base) {
508 if (!Base)
509 return;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000510 // Do we have expected type for Base?
511 if (ExpectedLoc != Base->getBeginLoc())
512 return;
513 // Keep the expected type, only update the location.
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000514 ExpectedLoc = Tok;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000515 return;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000516}
517
518void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,
519 tok::TokenKind OpKind,
520 SourceLocation OpLoc) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000521 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000522 Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);
523 ExpectedLoc = Tok;
524}
525
526void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,
527 Expr *LHS) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000528 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000529 Type = S.getASTContext().IntTy;
530 ExpectedLoc = Tok;
531}
532
533void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,
534 QualType CastType) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000535 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000536 Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();
537 ExpectedLoc = Tok;
538}
539
540void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000541 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000542 Type = S.getASTContext().BoolTy;
543 ExpectedLoc = Tok;
544}
545
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000546class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000547 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000548 unsigned SingleDeclIndex;
549
550public:
551 typedef DeclIndexPair value_type;
552 typedef value_type reference;
553 typedef std::ptrdiff_t difference_type;
554 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000555
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000556 class pointer {
557 DeclIndexPair Value;
558
559 public:
Fangrui Song050229d2018-11-24 00:14:31 +0000560 pointer(const DeclIndexPair &Value) : Value(Value) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000561
Fangrui Song050229d2018-11-24 00:14:31 +0000562 const DeclIndexPair *operator->() const { return &Value; }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000563 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000564
565 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000566
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000567 iterator(const NamedDecl *SingleDecl, unsigned Index)
Fangrui Song050229d2018-11-24 00:14:31 +0000568 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000569
570 iterator(const DeclIndexPair *Iterator)
Fangrui Song050229d2018-11-24 00:14:31 +0000571 : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000572
573 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000574 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000575 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000576 SingleDeclIndex = 0;
577 return *this;
578 }
579
Fangrui Song050229d2018-11-24 00:14:31 +0000580 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000581 ++I;
582 DeclOrIterator = I;
583 return *this;
584 }
585
Chris Lattner9795b392010-09-04 18:12:20 +0000586 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000587 iterator tmp(*this);
588 ++(*this);
589 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000590 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000591
592 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000593 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000594 return reference(ND, SingleDeclIndex);
595
Fangrui Song050229d2018-11-24 00:14:31 +0000596 return *DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000597 }
598
Fangrui Song050229d2018-11-24 00:14:31 +0000599 pointer operator->() const { return pointer(**this); }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000600
601 friend bool operator==(const iterator &X, const iterator &Y) {
Fangrui Song050229d2018-11-24 00:14:31 +0000602 return X.DeclOrIterator.getOpaqueValue() ==
603 Y.DeclOrIterator.getOpaqueValue() &&
604 X.SingleDeclIndex == Y.SingleDeclIndex;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000605 }
606
607 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000608 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000609 }
610};
611
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000612ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000613ResultBuilder::ShadowMapEntry::begin() const {
614 if (DeclOrVector.isNull())
615 return iterator();
616
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000617 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000618 return iterator(ND, SingleDeclIndex);
619
620 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
621}
622
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000623ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000624ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000625 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000626 return iterator();
627
628 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
629}
630
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000631/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000632/// (\p CurContext) to the target context (\p TargetContext).
633///
634/// \param Context the AST context in which the qualification will be used.
635///
636/// \param CurContext the context where an entity is being named, which is
637/// typically based on the current scope.
638///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000639/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000640/// resides.
641///
642/// \returns a nested name specifier that refers into the target context, or
643/// NULL if no qualification is needed.
644static NestedNameSpecifier *
Fangrui Song050229d2018-11-24 00:14:31 +0000645getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000646 const DeclContext *TargetContext) {
647 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000648
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000649 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000650 CommonAncestor && !CommonAncestor->Encloses(CurContext);
651 CommonAncestor = CommonAncestor->getLookupParent()) {
652 if (CommonAncestor->isTransparentContext() ||
653 CommonAncestor->isFunctionOrMethod())
654 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000655
Douglas Gregor2af2f672009-09-21 20:12:40 +0000656 TargetParents.push_back(CommonAncestor);
657 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000658
659 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000660 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000661 const DeclContext *Parent = TargetParents.pop_back_val();
662
Fangrui Song050229d2018-11-24 00:14:31 +0000663 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000664 if (!Namespace->getIdentifier())
665 continue;
666
Douglas Gregor2af2f672009-09-21 20:12:40 +0000667 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Fangrui Song050229d2018-11-24 00:14:31 +0000668 } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
669 Result = NestedNameSpecifier::Create(
670 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000671 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000672 return Result;
673}
674
Alp Toker034bbd52014-06-30 01:33:53 +0000675/// Determine whether \p Id is a name reserved for the implementation (C99
676/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000677static bool isReservedName(const IdentifierInfo *Id,
678 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000679 if (Id->getLength() < 2)
680 return false;
681 const char *Name = Id->getNameStart();
682 return Name[0] == '_' &&
Fangrui Song050229d2018-11-24 00:14:31 +0000683 (Name[1] == '_' ||
684 (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000685}
686
687// Some declarations have reserved names that we don't want to ever show.
688// Filter out names reserved for the implementation if they come from a
689// system header.
690static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
691 const IdentifierInfo *Id = ND->getIdentifier();
692 if (!Id)
693 return false;
694
695 // Ignore reserved names for compiler provided decls.
696 if (isReservedName(Id) && ND->getLocation().isInvalid())
697 return true;
698
699 // For system headers ignore only double-underscore names.
700 // This allows for system headers providing private symbols with a single
701 // underscore.
702 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000703 SemaRef.SourceMgr.isInSystemHeader(
704 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
705 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000706
707 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000708}
709
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000710bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000711 bool &AsNestedNameSpecifier) const {
712 AsNestedNameSpecifier = false;
713
Richard Smithf2005d32015-12-29 23:34:32 +0000714 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000715 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000716
717 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000718 if (!ND->getDeclName())
719 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000720
Douglas Gregor3545ff42009-09-21 16:56:56 +0000721 // Friend declarations and declarations introduced due to friends are never
722 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000723 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000724 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000725
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000726 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000727 if (isa<ClassTemplateSpecializationDecl>(ND) ||
728 isa<ClassTemplatePartialSpecializationDecl>(ND))
729 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000730
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000731 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000732 if (isa<UsingDecl>(ND))
733 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000734
735 if (shouldIgnoreDueToReservedName(ND, SemaRef))
736 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000737
Douglas Gregor59cab552010-08-16 23:05:20 +0000738 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000739 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
740 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000741 AsNestedNameSpecifier = true;
742
Douglas Gregor3545ff42009-09-21 16:56:56 +0000743 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000744 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000745 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000746 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000747 IsNestedNameSpecifier(ND) &&
748 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000749 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000750 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
751 AsNestedNameSpecifier = true;
752 return true;
753 }
754
Douglas Gregor7c208612010-01-14 00:20:49 +0000755 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000756 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000757 // ... then it must be interesting!
758 return true;
759}
760
Douglas Gregore0717ab2010-01-14 00:41:07 +0000761bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000762 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000763 // In C, there is no way to refer to a hidden name.
764 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
765 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000766 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000767 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000768
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000769 const DeclContext *HiddenCtx =
770 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000771
Douglas Gregore0717ab2010-01-14 00:41:07 +0000772 // There is no way to qualify a name declared in a function or method.
773 if (HiddenCtx->isFunctionOrMethod())
774 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000775
Sebastian Redl50c68252010-08-31 00:36:30 +0000776 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000777 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000778
Douglas Gregore0717ab2010-01-14 00:41:07 +0000779 // We can refer to the result with the appropriate qualification. Do it.
780 R.Hidden = true;
781 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000782
Douglas Gregore0717ab2010-01-14 00:41:07 +0000783 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000784 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000785 R.Declaration->getDeclContext());
786 return false;
787}
788
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000789/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000790/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000791SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000792 switch (T->getTypeClass()) {
793 case Type::Builtin:
794 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000795 case BuiltinType::Void:
796 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000797
Fangrui Song050229d2018-11-24 00:14:31 +0000798 case BuiltinType::NullPtr:
799 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000800
Fangrui Song050229d2018-11-24 00:14:31 +0000801 case BuiltinType::Overload:
802 case BuiltinType::Dependent:
803 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000804
Fangrui Song050229d2018-11-24 00:14:31 +0000805 case BuiltinType::ObjCId:
806 case BuiltinType::ObjCClass:
807 case BuiltinType::ObjCSel:
808 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000809
Fangrui Song050229d2018-11-24 00:14:31 +0000810 default:
811 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000812 }
David Blaikie8a40f702012-01-17 06:56:22 +0000813
Douglas Gregor95887f92010-07-08 23:20:03 +0000814 case Type::Complex:
815 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000816
Douglas Gregor95887f92010-07-08 23:20:03 +0000817 case Type::Pointer:
818 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000819
Douglas Gregor95887f92010-07-08 23:20:03 +0000820 case Type::BlockPointer:
821 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000822
Douglas Gregor95887f92010-07-08 23:20:03 +0000823 case Type::LValueReference:
824 case Type::RValueReference:
825 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000826
Douglas Gregor95887f92010-07-08 23:20:03 +0000827 case Type::ConstantArray:
828 case Type::IncompleteArray:
829 case Type::VariableArray:
830 case Type::DependentSizedArray:
831 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000832
Douglas Gregor95887f92010-07-08 23:20:03 +0000833 case Type::DependentSizedExtVector:
834 case Type::Vector:
835 case Type::ExtVector:
836 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000837
Douglas Gregor95887f92010-07-08 23:20:03 +0000838 case Type::FunctionProto:
839 case Type::FunctionNoProto:
840 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000841
Douglas Gregor95887f92010-07-08 23:20:03 +0000842 case Type::Record:
843 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000844
Douglas Gregor95887f92010-07-08 23:20:03 +0000845 case Type::Enum:
846 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000847
Douglas Gregor95887f92010-07-08 23:20:03 +0000848 case Type::ObjCObject:
849 case Type::ObjCInterface:
850 case Type::ObjCObjectPointer:
851 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000852
Douglas Gregor95887f92010-07-08 23:20:03 +0000853 default:
854 return STC_Other;
855 }
856}
857
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000858/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000859/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000860QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000861 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000862
Fangrui Song050229d2018-11-24 00:14:31 +0000863 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000864 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000865 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000866 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000867
Douglas Gregor95887f92010-07-08 23:20:03 +0000868 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000869 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000870 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000871 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000872 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000873 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000874 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000875 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000876 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000877 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000878 T = Value->getType();
Ilya Biryukovc514ade2019-01-24 10:41:43 +0000879
880 if (T.isNull())
Douglas Gregor95887f92010-07-08 23:20:03 +0000881 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000882
883 // Dig through references, function pointers, and block pointers to
884 // get down to the likely type of an expression when the entity is
885 // used.
886 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000887 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000888 T = Ref->getPointeeType();
889 continue;
890 }
891
Fangrui Song050229d2018-11-24 00:14:31 +0000892 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000893 if (Pointer->getPointeeType()->isFunctionType()) {
894 T = Pointer->getPointeeType();
895 continue;
896 }
897
898 break;
899 }
900
Fangrui Song050229d2018-11-24 00:14:31 +0000901 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000902 T = Block->getPointeeType();
903 continue;
904 }
905
Fangrui Song050229d2018-11-24 00:14:31 +0000906 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000907 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000908 continue;
909 }
910
911 break;
912 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000913
Douglas Gregoraf670a82011-04-14 20:33:34 +0000914 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000915}
916
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000917unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
918 if (!ND)
919 return CCP_Unlikely;
920
921 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000922 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
923 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000924 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000925 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000926 if (ImplicitParam->getIdentifier() &&
927 ImplicitParam->getIdentifier()->isStr("_cmd"))
928 return CCP_ObjC_cmd;
929
930 return CCP_LocalDeclaration;
931 }
Richard Smith541b38b2013-09-20 01:15:31 +0000932
933 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000934 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
935 // Explicit destructor calls are very rare.
936 if (isa<CXXDestructorDecl>(ND))
937 return CCP_Unlikely;
938 // Explicit operator and conversion function calls are also very rare.
939 auto DeclNameKind = ND->getDeclName().getNameKind();
940 if (DeclNameKind == DeclarationName::CXXOperatorName ||
941 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
942 DeclNameKind == DeclarationName::CXXConversionFunctionName)
943 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000944 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000945 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000946
947 // Content-based decisions.
948 if (isa<EnumConstantDecl>(ND))
949 return CCP_Constant;
950
Douglas Gregor52e0de42013-01-31 05:03:46 +0000951 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
952 // message receiver, or parenthesized expression context. There, it's as
953 // likely that the user will want to write a type as other declarations.
954 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
955 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000956 CompletionContext.getKind() ==
957 CodeCompletionContext::CCC_ObjCMessageReceiver ||
958 CompletionContext.getKind() ==
959 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000960 return CCP_Type;
961
962 return CCP_Declaration;
963}
964
Douglas Gregor50832e02010-09-20 22:39:41 +0000965void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
966 // If this is an Objective-C method declaration whose selector matches our
967 // preferred selector, give it a priority boost.
968 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000969 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000970 if (PreferredSelector == Method->getSelector())
971 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000972
Douglas Gregor50832e02010-09-20 22:39:41 +0000973 // If we have a preferred type, adjust the priority for results with exactly-
974 // matching or nearly-matching types.
975 if (!PreferredType.isNull()) {
976 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
977 if (!T.isNull()) {
978 CanQualType TC = SemaRef.Context.getCanonicalType(T);
979 // Check for exactly-matching types (modulo qualifiers).
980 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
981 R.Priority /= CCF_ExactTypeMatch;
982 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +0000983 else if ((getSimplifiedTypeClass(PreferredType) ==
984 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000985 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000986 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000987 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000988 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000989}
990
Benjamin Kramer756ecb82019-02-11 14:52:15 +0000991static DeclContext::lookup_result getConstructors(ASTContext &Context,
992 const CXXRecordDecl *Record) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +0000993 QualType RecordTy = Context.getTypeDeclType(Record);
994 DeclarationName ConstructorName =
995 Context.DeclarationNames.getCXXConstructorName(
996 Context.getCanonicalType(RecordTy));
997 return Record->lookup(ConstructorName);
998}
999
Douglas Gregor0212fd72010-09-21 16:06:22 +00001000void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001001 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +00001002 !CompletionContext.wantConstructorResults())
1003 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001004
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001005 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +00001006 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001007 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001008 Record = ClassTemplate->getTemplatedDecl();
1009 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
1010 // Skip specializations and partial specializations.
1011 if (isa<ClassTemplateSpecializationDecl>(Record))
1012 return;
1013 } else {
1014 // There are no constructors here.
1015 return;
1016 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001017
Douglas Gregor0212fd72010-09-21 16:06:22 +00001018 Record = Record->getDefinition();
1019 if (!Record)
1020 return;
1021
Fangrui Song050229d2018-11-24 00:14:31 +00001022 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001023 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001024 R.CursorKind = getCursorKindForDecl(R.Declaration);
1025 Results.push_back(R);
1026 }
1027}
1028
Sam McCall63c59722018-01-22 20:44:47 +00001029static bool isConstructor(const Decl *ND) {
1030 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
1031 ND = Tmpl->getTemplatedDecl();
1032 return isa<CXXConstructorDecl>(ND);
1033}
1034
Douglas Gregor7c208612010-01-14 00:20:49 +00001035void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
1036 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001037
Douglas Gregor7c208612010-01-14 00:20:49 +00001038 if (R.Kind != Result::RK_Declaration) {
1039 // For non-declaration results, just add the result.
1040 Results.push_back(R);
1041 return;
1042 }
1043
1044 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001045 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
1046 CodeCompletionResult Result(Using->getTargetDecl(),
1047 getBasePriority(Using->getTargetDecl()),
1048 R.Qualifier);
1049 Result.ShadowDecl = Using;
1050 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +00001051 return;
1052 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001053
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001054 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +00001055 unsigned IDNS = CanonDecl->getIdentifierNamespace();
1056
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001057 bool AsNestedNameSpecifier = false;
1058 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +00001059 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001060
Douglas Gregor0212fd72010-09-21 16:06:22 +00001061 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001062 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001063 return;
1064
Douglas Gregor3545ff42009-09-21 16:56:56 +00001065 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001066 ShadowMapEntry::iterator I, IEnd;
1067 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
1068 if (NamePos != SMap.end()) {
1069 I = NamePos->second.begin();
1070 IEnd = NamePos->second.end();
1071 }
1072
1073 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001074 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001075 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001076 if (ND->getCanonicalDecl() == CanonDecl) {
1077 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001078 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001079
Douglas Gregor3545ff42009-09-21 16:56:56 +00001080 // We're done.
1081 return;
1082 }
1083 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001084
Douglas Gregor3545ff42009-09-21 16:56:56 +00001085 // This is a new declaration in this scope. However, check whether this
1086 // declaration name is hidden by a similarly-named declaration in an outer
1087 // scope.
1088 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
1089 --SMEnd;
1090 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001091 ShadowMapEntry::iterator I, IEnd;
1092 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
1093 if (NamePos != SM->end()) {
1094 I = NamePos->second.begin();
1095 IEnd = NamePos->second.end();
1096 }
1097 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001098 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +00001099 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +00001100 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
1101 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001102 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001103
Douglas Gregor3545ff42009-09-21 16:56:56 +00001104 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +00001105 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
1106 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001107 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001108 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001109
Douglas Gregor3545ff42009-09-21 16:56:56 +00001110 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +00001111 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001112 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001113
Douglas Gregor3545ff42009-09-21 16:56:56 +00001114 break;
1115 }
1116 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001117
Douglas Gregor3545ff42009-09-21 16:56:56 +00001118 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001119 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001120 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00001121
Douglas Gregore412a5a2009-09-23 22:26:46 +00001122 // If the filter is for nested-name-specifiers, then this result starts a
1123 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001124 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +00001125 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001126 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001127 } else
Fangrui Song050229d2018-11-24 00:14:31 +00001128 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001129
Douglas Gregor5bf52692009-09-22 23:15:58 +00001130 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +00001131 if (R.QualifierIsInformative && !R.Qualifier &&
1132 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001133 const DeclContext *Ctx = R.Declaration->getDeclContext();
1134 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001135 R.Qualifier =
1136 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001137 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001138 R.Qualifier = NestedNameSpecifier::Create(
1139 SemaRef.Context, nullptr, false,
1140 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +00001141 else
1142 R.QualifierIsInformative = false;
1143 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001144
Douglas Gregor3545ff42009-09-21 16:56:56 +00001145 // Insert this result into the set of results and into the current shadow
1146 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001147 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001148 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001149
Douglas Gregor0212fd72010-09-21 16:06:22 +00001150 if (!AsNestedNameSpecifier)
1151 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001152}
1153
Eric Liu4a7cd632018-10-24 12:57:27 +00001154static void setInBaseClass(ResultBuilder::Result &R) {
1155 R.Priority += CCD_InBaseClass;
1156 R.InBaseClass = true;
1157}
1158
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001159void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +00001160 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001161 if (R.Kind != Result::RK_Declaration) {
1162 // For non-declaration results, just add the result.
1163 Results.push_back(R);
1164 return;
1165 }
1166
Douglas Gregorc580c522010-01-14 01:09:38 +00001167 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +00001168 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001169 CodeCompletionResult Result(Using->getTargetDecl(),
1170 getBasePriority(Using->getTargetDecl()),
1171 R.Qualifier);
1172 Result.ShadowDecl = Using;
1173 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +00001174 return;
1175 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001176
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001177 bool AsNestedNameSpecifier = false;
1178 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +00001179 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001180
Douglas Gregor0212fd72010-09-21 16:06:22 +00001181 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001182 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001183 return;
1184
Douglas Gregorc580c522010-01-14 01:09:38 +00001185 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1186 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001187
Douglas Gregorc580c522010-01-14 01:09:38 +00001188 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001189 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001190 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001191
Douglas Gregorc580c522010-01-14 01:09:38 +00001192 // If the filter is for nested-name-specifiers, then this result starts a
1193 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001194 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001195 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001196 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001197 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1198 InBaseClass &&
1199 isa<CXXRecordDecl>(
1200 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001201 R.QualifierIsInformative = true;
1202
Douglas Gregorc580c522010-01-14 01:09:38 +00001203 // If this result is supposed to have an informative qualifier, add one.
1204 if (R.QualifierIsInformative && !R.Qualifier &&
1205 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001206 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001207 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1208 R.Qualifier =
1209 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1210 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1211 R.Qualifier = NestedNameSpecifier::Create(
1212 SemaRef.Context, nullptr, false,
1213 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001214 else
1215 R.QualifierIsInformative = false;
1216 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001217
Douglas Gregora2db7932010-05-26 22:00:08 +00001218 // Adjust the priority if this result comes from a base class.
1219 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001220 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001221
Douglas Gregor50832e02010-09-20 22:39:41 +00001222 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001223
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001224 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001225 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001226 if (Method->isInstance()) {
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00001227 Qualifiers MethodQuals = Method->getMethodQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001228 if (ObjectTypeQualifiers == MethodQuals)
1229 R.Priority += CCD_ObjectQualifierMatch;
1230 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001231 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001232 // qualifiers.
1233 return;
1234 }
1235 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001236
Douglas Gregorc580c522010-01-14 01:09:38 +00001237 // Insert this result into the set of results.
1238 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001239
Douglas Gregor0212fd72010-09-21 16:06:22 +00001240 if (!AsNestedNameSpecifier)
1241 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001242}
1243
Douglas Gregor78a21012010-01-14 16:01:26 +00001244void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001245 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001246 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001247 Results.push_back(R);
1248}
1249
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001250/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001251void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001252
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001253/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001254void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001255 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00001256 EEnd = ShadowMaps.back().end();
1257 E != EEnd; ++E)
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001258 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001259
Douglas Gregor3545ff42009-09-21 16:56:56 +00001260 ShadowMaps.pop_back();
1261}
1262
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001263/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001264/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001265bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001266 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001267
Richard Smith541b38b2013-09-20 01:15:31 +00001268 // If name lookup finds a local extern declaration, then we are in a
1269 // context where it behaves like an ordinary name.
1270 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001271 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001272 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001273 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001274 if (isa<ObjCIvarDecl>(ND))
1275 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001276 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001277
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001278 return ND->getIdentifierNamespace() & IDNS;
1279}
1280
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001281/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001282/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001283bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001284 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001285 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001286 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001287 // Objective-C interfaces names are not filtered by this method because they
1288 // can be used in a class property expression. We can still filter out
1289 // @class declarations though.
1290 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1291 if (!ID->getDefinition())
1292 return false;
1293 }
1294
Richard Smith541b38b2013-09-20 01:15:31 +00001295 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001296 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001297 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001298 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001299 if (isa<ObjCIvarDecl>(ND))
1300 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001301 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001302
Douglas Gregor70febae2010-05-28 00:49:12 +00001303 return ND->getIdentifierNamespace() & IDNS;
1304}
1305
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001306bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001307 if (!IsOrdinaryNonTypeName(ND))
1308 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001309
Fangrui Song050229d2018-11-24 00:14:31 +00001310 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001311 if (VD->getType()->isIntegralOrEnumerationType())
1312 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001313
Douglas Gregor85b50632010-07-28 21:50:18 +00001314 return false;
1315}
1316
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001317/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001318/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001319bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001320 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001321
Richard Smith541b38b2013-09-20 01:15:31 +00001322 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001323 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001324 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001325
Fangrui Song050229d2018-11-24 00:14:31 +00001326 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1327 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001328}
1329
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001330/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001331/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001332bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001333 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001334 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001335 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001336
Douglas Gregor3545ff42009-09-21 16:56:56 +00001337 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1338}
1339
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001340/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001341bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001342 return isa<EnumDecl>(ND);
1343}
1344
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001345/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001346bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001347 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001348 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001349 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001350
1351 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001352 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1353 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1354 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001355
Douglas Gregor3545ff42009-09-21 16:56:56 +00001356 return false;
1357}
1358
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001359/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001360bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001361 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001362 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001363 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001364
Fangrui Song050229d2018-11-24 00:14:31 +00001365 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001366 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001367
Douglas Gregor3545ff42009-09-21 16:56:56 +00001368 return false;
1369}
1370
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001371/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001372bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001373 return isa<NamespaceDecl>(ND);
1374}
1375
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001376/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001377/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001378bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001379 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001380}
1381
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001382/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001383bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001384 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001385 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001386}
1387
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001388/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001389/// "." or "->". Only value declarations, nested name specifiers, and
1390/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001391bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001392 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001393 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001394 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001395}
1396
Douglas Gregora817a192010-05-27 23:06:34 +00001397static bool isObjCReceiverType(ASTContext &C, QualType T) {
1398 T = C.getCanonicalType(T);
1399 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001400 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001401 case Type::ObjCInterface:
1402 case Type::ObjCObjectPointer:
1403 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001404
Douglas Gregora817a192010-05-27 23:06:34 +00001405 case Type::Builtin:
1406 switch (cast<BuiltinType>(T)->getKind()) {
1407 case BuiltinType::ObjCId:
1408 case BuiltinType::ObjCClass:
1409 case BuiltinType::ObjCSel:
1410 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001411
Douglas Gregora817a192010-05-27 23:06:34 +00001412 default:
1413 break;
1414 }
1415 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001416
Douglas Gregora817a192010-05-27 23:06:34 +00001417 default:
1418 break;
1419 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001420
David Blaikiebbafb8a2012-03-11 07:00:24 +00001421 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001422 return false;
1423
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001424 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001425 // particular class type has any conversions to Objective-C types. For now,
1426 // just accept all class types.
1427 return T->isDependentType() || T->isRecordType();
1428}
1429
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001430bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001431 QualType T = getDeclUsageType(SemaRef.Context, ND);
1432 if (T.isNull())
1433 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001434
Douglas Gregora817a192010-05-27 23:06:34 +00001435 T = SemaRef.Context.getBaseElementType(T);
1436 return isObjCReceiverType(SemaRef.Context, T);
1437}
1438
Fangrui Song050229d2018-11-24 00:14:31 +00001439bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1440 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001441 if (IsObjCMessageReceiver(ND))
1442 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001443
Fangrui Song050229d2018-11-24 00:14:31 +00001444 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001445 if (!Var)
1446 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001447
Douglas Gregord8c61782012-02-15 15:34:24 +00001448 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1449}
1450
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001451bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001452 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1453 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001454 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001455
Douglas Gregor68762e72010-08-23 21:17:50 +00001456 QualType T = getDeclUsageType(SemaRef.Context, ND);
1457 if (T.isNull())
1458 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001459
Douglas Gregor68762e72010-08-23 21:17:50 +00001460 T = SemaRef.Context.getBaseElementType(T);
1461 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001462 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001463 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001464}
Douglas Gregora817a192010-05-27 23:06:34 +00001465
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001466bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001467 return false;
1468}
1469
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001470/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001471/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001472bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001473 return isa<ObjCIvarDecl>(ND);
1474}
1475
Douglas Gregorc580c522010-01-14 01:09:38 +00001476namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001477
Fangrui Song050229d2018-11-24 00:14:31 +00001478/// Visible declaration consumer that adds a code-completion result
1479/// for each visible declaration.
1480class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1481 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001482 DeclContext *InitialLookupCtx;
1483 // NamingClass and BaseType are used for access-checking. See
1484 // Sema::IsSimplyAccessible for details.
1485 CXXRecordDecl *NamingClass;
1486 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001487 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001488
Fangrui Song050229d2018-11-24 00:14:31 +00001489public:
1490 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001491 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1492 QualType BaseType = QualType(),
1493 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1494 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1495 FixIts(std::move(FixIts)) {
1496 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1497 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1498 if (BaseType.isNull()) {
1499 auto ThisType = Results.getSema().getCurrentThisType();
1500 if (!ThisType.isNull()) {
1501 assert(ThisType->isPointerType());
1502 BaseType = ThisType->getPointeeType();
1503 if (!NamingClass)
1504 NamingClass = BaseType->getAsCXXRecordDecl();
1505 }
1506 }
1507 this->BaseType = BaseType;
1508 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001509
Fangrui Song050229d2018-11-24 00:14:31 +00001510 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1511 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001512 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001513 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001514 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001515 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001516
Fangrui Song050229d2018-11-24 00:14:31 +00001517 void EnteredContext(DeclContext *Ctx) override {
1518 Results.addVisitedContext(Ctx);
1519 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001520
1521private:
1522 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1523 // Naming class to use for access check. In most cases it was provided
1524 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1525 // for unqualified lookup we fallback to the \p Ctx in which we found the
1526 // member.
1527 auto *NamingClass = this->NamingClass;
1528 QualType BaseType = this->BaseType;
1529 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1530 if (!NamingClass)
1531 NamingClass = Cls;
1532 // When we emulate implicit 'this->' in an unqualified lookup, we might
1533 // end up with an invalid naming class. In that case, we avoid emulating
1534 // 'this->' qualifier to satisfy preconditions of the access checking.
1535 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1536 !NamingClass->isDerivedFrom(Cls)) {
1537 NamingClass = Cls;
1538 BaseType = QualType();
1539 }
1540 } else {
1541 // The decl was found outside the C++ class, so only ObjC access checks
1542 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1543 // out.
1544 NamingClass = nullptr;
1545 BaseType = QualType();
1546 }
1547 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1548 }
Fangrui Song050229d2018-11-24 00:14:31 +00001549};
1550} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001551
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001552/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001553static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001554 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001555 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001556 Results.AddResult(Result("short", CCP_Type));
1557 Results.AddResult(Result("long", CCP_Type));
1558 Results.AddResult(Result("signed", CCP_Type));
1559 Results.AddResult(Result("unsigned", CCP_Type));
1560 Results.AddResult(Result("void", CCP_Type));
1561 Results.AddResult(Result("char", CCP_Type));
1562 Results.AddResult(Result("int", CCP_Type));
1563 Results.AddResult(Result("float", CCP_Type));
1564 Results.AddResult(Result("double", CCP_Type));
1565 Results.AddResult(Result("enum", CCP_Type));
1566 Results.AddResult(Result("struct", CCP_Type));
1567 Results.AddResult(Result("union", CCP_Type));
1568 Results.AddResult(Result("const", CCP_Type));
1569 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001570
Douglas Gregor3545ff42009-09-21 16:56:56 +00001571 if (LangOpts.C99) {
1572 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001573 Results.AddResult(Result("_Complex", CCP_Type));
1574 Results.AddResult(Result("_Imaginary", CCP_Type));
1575 Results.AddResult(Result("_Bool", CCP_Type));
1576 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001577 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001578
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001579 CodeCompletionBuilder Builder(Results.getAllocator(),
1580 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001581 if (LangOpts.CPlusPlus) {
1582 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001583 Results.AddResult(
1584 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001585 Results.AddResult(Result("class", CCP_Type));
1586 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001587
Douglas Gregorf4c33342010-05-28 00:22:41 +00001588 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001589 Builder.AddTypedTextChunk("typename");
1590 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1591 Builder.AddPlaceholderChunk("qualifier");
1592 Builder.AddTextChunk("::");
1593 Builder.AddPlaceholderChunk("name");
1594 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001595
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001596 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001597 Results.AddResult(Result("auto", CCP_Type));
1598 Results.AddResult(Result("char16_t", CCP_Type));
1599 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001600
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001601 Builder.AddTypedTextChunk("decltype");
1602 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1603 Builder.AddPlaceholderChunk("expression");
1604 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1605 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001606 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001607 } else
1608 Results.AddResult(Result("__auto_type", CCP_Type));
1609
Richard Smith7b301e22018-05-24 21:51:52 +00001610 // GNU keywords
1611 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001612 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001613 // Results.AddResult(Result("_Decimal32"));
1614 // Results.AddResult(Result("_Decimal64"));
1615 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001616
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001617 Builder.AddTypedTextChunk("typeof");
1618 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1619 Builder.AddPlaceholderChunk("expression");
1620 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001621
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001622 Builder.AddTypedTextChunk("typeof");
1623 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1624 Builder.AddPlaceholderChunk("type");
1625 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1626 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001627 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001628
1629 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001630 Results.AddResult(Result("_Nonnull", CCP_Type));
1631 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1632 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001633}
1634
John McCallfaf5fb42010-08-26 23:41:50 +00001635static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001636 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001637 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001638 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001639 // Note: we don't suggest either "auto" or "register", because both
1640 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1641 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001642 Results.AddResult(Result("extern"));
1643 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001644
1645 if (LangOpts.CPlusPlus11) {
1646 CodeCompletionAllocator &Allocator = Results.getAllocator();
1647 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1648
1649 // alignas
1650 Builder.AddTypedTextChunk("alignas");
1651 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1652 Builder.AddPlaceholderChunk("expression");
1653 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1654 Results.AddResult(Result(Builder.TakeString()));
1655
1656 Results.AddResult(Result("constexpr"));
1657 Results.AddResult(Result("thread_local"));
1658 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001659}
1660
John McCallfaf5fb42010-08-26 23:41:50 +00001661static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001662 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001663 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001664 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001665 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001666 case Sema::PCC_Class:
1667 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001668 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001669 Results.AddResult(Result("explicit"));
1670 Results.AddResult(Result("friend"));
1671 Results.AddResult(Result("mutable"));
1672 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001673 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001674 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001675
John McCallfaf5fb42010-08-26 23:41:50 +00001676 case Sema::PCC_ObjCInterface:
1677 case Sema::PCC_ObjCImplementation:
1678 case Sema::PCC_Namespace:
1679 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001680 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001681 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001682 break;
1683
John McCallfaf5fb42010-08-26 23:41:50 +00001684 case Sema::PCC_ObjCInstanceVariableList:
1685 case Sema::PCC_Expression:
1686 case Sema::PCC_Statement:
1687 case Sema::PCC_ForInit:
1688 case Sema::PCC_Condition:
1689 case Sema::PCC_RecoveryInFunction:
1690 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001691 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001692 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001693 break;
1694 }
1695}
1696
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001697static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1698static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1699static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001700 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001701static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001702 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001703static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001704 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001705static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001706
Douglas Gregorf4c33342010-05-28 00:22:41 +00001707static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001708 CodeCompletionBuilder Builder(Results.getAllocator(),
1709 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001710 Builder.AddTypedTextChunk("typedef");
1711 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1712 Builder.AddPlaceholderChunk("type");
1713 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1714 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001715 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001716}
1717
John McCallfaf5fb42010-08-26 23:41:50 +00001718static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001719 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001720 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001721 case Sema::PCC_Namespace:
1722 case Sema::PCC_Class:
1723 case Sema::PCC_ObjCInstanceVariableList:
1724 case Sema::PCC_Template:
1725 case Sema::PCC_MemberTemplate:
1726 case Sema::PCC_Statement:
1727 case Sema::PCC_RecoveryInFunction:
1728 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001729 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001730 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001731 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001732
John McCallfaf5fb42010-08-26 23:41:50 +00001733 case Sema::PCC_Expression:
1734 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001735 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001736
Douglas Gregor5e35d592010-09-14 23:59:36 +00001737 case Sema::PCC_ObjCInterface:
1738 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001739 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001740
John McCallfaf5fb42010-08-26 23:41:50 +00001741 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001742 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001743 }
David Blaikie8a40f702012-01-17 06:56:22 +00001744
1745 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001746}
1747
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001748static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1749 const Preprocessor &PP) {
1750 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001751 Policy.AnonymousTagLocations = false;
1752 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001753 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001754 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001755 return Policy;
1756}
1757
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001758/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001759static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1760 return getCompletionPrintingPolicy(S.Context, S.PP);
1761}
1762
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001763/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001764/// that has the appropriate lifetime for code completion.
1765///
1766/// This routine provides a fast path where we provide constant strings for
1767/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001768static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001769 const PrintingPolicy &Policy,
1770 CodeCompletionAllocator &Allocator) {
1771 if (!T.getLocalQualifiers()) {
1772 // Built-in type names are constant strings.
1773 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001774 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001775
Douglas Gregore5c79d52011-10-18 21:20:17 +00001776 // Anonymous tag types are constant strings.
1777 if (const TagType *TagT = dyn_cast<TagType>(T))
1778 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001779 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001780 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001781 case TTK_Struct:
1782 return "struct <anonymous>";
1783 case TTK_Interface:
1784 return "__interface <anonymous>";
1785 case TTK_Class:
1786 return "class <anonymous>";
1787 case TTK_Union:
1788 return "union <anonymous>";
1789 case TTK_Enum:
1790 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001791 }
1792 }
1793 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001794
Douglas Gregore5c79d52011-10-18 21:20:17 +00001795 // Slow path: format the type as a string.
1796 std::string Result;
1797 T.getAsStringInternal(Result, Policy);
1798 return Allocator.CopyString(Result);
1799}
1800
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001801/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001802static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1803 QualType ThisTy = S.getCurrentThisType();
1804 if (ThisTy.isNull())
1805 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001806
Douglas Gregord8c61782012-02-15 15:34:24 +00001807 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001808 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001809 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001810 Builder.AddResultTypeChunk(
1811 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001812 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001813 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001814}
1815
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001816static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1817 ResultBuilder &Results,
1818 const LangOptions &LangOpts) {
1819 if (!LangOpts.CPlusPlus11)
1820 return;
1821
1822 Builder.AddTypedTextChunk("static_assert");
1823 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1824 Builder.AddPlaceholderChunk("expression");
1825 Builder.AddChunk(CodeCompletionString::CK_Comma);
1826 Builder.AddPlaceholderChunk("message");
1827 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1828 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1829}
1830
Fangrui Song050229d2018-11-24 00:14:31 +00001831static void printOverrideString(llvm::raw_ostream &OS,
1832 CodeCompletionString *CCS) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001833 for (const auto &C : *CCS) {
1834 if (C.Kind == CodeCompletionString::CK_Optional)
1835 printOverrideString(OS, C.Optional);
1836 else
1837 OS << C.Text;
1838 // Add a space after return type.
1839 if (C.Kind == CodeCompletionString::CK_ResultType)
1840 OS << ' ';
1841 }
1842}
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001843
1844static void AddOverrideResults(ResultBuilder &Results,
1845 const CodeCompletionContext &CCContext,
1846 CodeCompletionBuilder &Builder) {
1847 Sema &S = Results.getSema();
1848 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1849 // If not inside a class/struct/union return empty.
1850 if (!CR)
1851 return;
1852 // First store overrides within current class.
1853 // These are stored by name to make querying fast in the later step.
1854 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1855 for (auto *Method : CR->methods()) {
1856 if (!Method->isVirtual() || !Method->getIdentifier())
1857 continue;
1858 Overrides[Method->getName()].push_back(Method);
1859 }
1860
1861 for (const auto &Base : CR->bases()) {
1862 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1863 if (!BR)
1864 continue;
1865 for (auto *Method : BR->methods()) {
1866 if (!Method->isVirtual() || !Method->getIdentifier())
1867 continue;
1868 const auto it = Overrides.find(Method->getName());
1869 bool IsOverriden = false;
1870 if (it != Overrides.end()) {
1871 for (auto *MD : it->second) {
1872 // If the method in current body is not an overload of this virtual
1873 // function, then it overrides this one.
1874 if (!S.IsOverload(MD, Method, false)) {
1875 IsOverriden = true;
1876 break;
1877 }
1878 }
1879 }
1880 if (!IsOverriden) {
1881 // Generates a new CodeCompletionResult by taking this function and
1882 // converting it into an override declaration with only one chunk in the
1883 // final CodeCompletionString as a TypedTextChunk.
1884 std::string OverrideSignature;
1885 llvm::raw_string_ostream OS(OverrideSignature);
1886 CodeCompletionResult CCR(Method, 0);
1887 PrintingPolicy Policy =
1888 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1889 auto *CCS = CCR.createCodeCompletionStringForOverride(
1890 S.getPreprocessor(), S.getASTContext(), Builder,
1891 /*IncludeBriefComments=*/false, CCContext, Policy);
1892 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1893 }
1894 }
1895 }
1896}
1897
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001898/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001899static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1900 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001901 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001902 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001903
John McCall276321a2010-08-25 06:19:51 +00001904 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001905 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001906 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001907 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001908 if (Results.includeCodePatterns()) {
1909 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001910 Builder.AddTypedTextChunk("namespace");
1911 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1912 Builder.AddPlaceholderChunk("identifier");
1913 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1914 Builder.AddPlaceholderChunk("declarations");
1915 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1916 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1917 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001918 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001919
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001920 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001921 Builder.AddTypedTextChunk("namespace");
1922 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1923 Builder.AddPlaceholderChunk("name");
1924 Builder.AddChunk(CodeCompletionString::CK_Equal);
1925 Builder.AddPlaceholderChunk("namespace");
1926 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001927
1928 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001929 Builder.AddTypedTextChunk("using");
1930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1931 Builder.AddTextChunk("namespace");
1932 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1933 Builder.AddPlaceholderChunk("identifier");
1934 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001935
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001936 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001937 Builder.AddTypedTextChunk("asm");
1938 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1939 Builder.AddPlaceholderChunk("string-literal");
1940 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1941 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001942
Douglas Gregorf4c33342010-05-28 00:22:41 +00001943 if (Results.includeCodePatterns()) {
1944 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001945 Builder.AddTypedTextChunk("template");
1946 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1947 Builder.AddPlaceholderChunk("declaration");
1948 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001949 } else {
1950 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001951 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001952 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001953
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001954 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001955 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001956
Douglas Gregorf4c33342010-05-28 00:22:41 +00001957 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001958 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001959
John McCallfaf5fb42010-08-26 23:41:50 +00001960 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001961 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001962 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001963 Builder.AddTypedTextChunk("using");
1964 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1965 Builder.AddPlaceholderChunk("qualifier");
1966 Builder.AddTextChunk("::");
1967 Builder.AddPlaceholderChunk("name");
1968 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001969
Douglas Gregorf4c33342010-05-28 00:22:41 +00001970 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001971 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001972 Builder.AddTypedTextChunk("using");
1973 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1974 Builder.AddTextChunk("typename");
1975 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1976 Builder.AddPlaceholderChunk("qualifier");
1977 Builder.AddTextChunk("::");
1978 Builder.AddPlaceholderChunk("name");
1979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001980 }
1981
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001982 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1983
John McCallfaf5fb42010-08-26 23:41:50 +00001984 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001985 AddTypedefResult(Results);
1986
Erik Verbruggen6524c052017-10-24 13:46:58 +00001987 bool IsNotInheritanceScope =
1988 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001989 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001990 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001991 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001992 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001993 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001994
1995 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001996 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001997 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001998 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001999 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002000
2001 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002002 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002003 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002004 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002005 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002006
2007 // FIXME: This adds override results only if we are at the first word of
2008 // the declaration/definition. Also call this from other sides to have
2009 // more use-cases.
2010 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
2011 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002012 }
2013 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002014 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002015
John McCallfaf5fb42010-08-26 23:41:50 +00002016 case Sema::PCC_Template:
2017 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002018 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002019 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002020 Builder.AddTypedTextChunk("template");
2021 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2022 Builder.AddPlaceholderChunk("parameters");
2023 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2024 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002025 } else {
2026 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002027 }
2028
David Blaikiebbafb8a2012-03-11 07:00:24 +00002029 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2030 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002031 break;
2032
John McCallfaf5fb42010-08-26 23:41:50 +00002033 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002034 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2035 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2036 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002037 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002038
John McCallfaf5fb42010-08-26 23:41:50 +00002039 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002040 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2041 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2042 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002043 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002044
John McCallfaf5fb42010-08-26 23:41:50 +00002045 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002046 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002047 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002048
John McCallfaf5fb42010-08-26 23:41:50 +00002049 case Sema::PCC_RecoveryInFunction:
2050 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002051 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002052
David Blaikiebbafb8a2012-03-11 07:00:24 +00002053 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2054 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002055 Builder.AddTypedTextChunk("try");
2056 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2057 Builder.AddPlaceholderChunk("statements");
2058 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2059 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2060 Builder.AddTextChunk("catch");
2061 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2062 Builder.AddPlaceholderChunk("declaration");
2063 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2064 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2065 Builder.AddPlaceholderChunk("statements");
2066 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2067 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2068 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002069 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002070 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002071 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002072
Douglas Gregorf64acca2010-05-25 21:41:55 +00002073 if (Results.includeCodePatterns()) {
2074 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002075 Builder.AddTypedTextChunk("if");
2076 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002077 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002078 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002079 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002080 Builder.AddPlaceholderChunk("expression");
2081 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2082 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2083 Builder.AddPlaceholderChunk("statements");
2084 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2085 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2086 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002087
Douglas Gregorf64acca2010-05-25 21:41:55 +00002088 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002089 Builder.AddTypedTextChunk("switch");
2090 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002091 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002092 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002093 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002094 Builder.AddPlaceholderChunk("expression");
2095 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2096 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2097 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2098 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2099 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002100 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002101
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002102 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002103 if (SemaRef.getCurFunction() &&
2104 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002105 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002106 Builder.AddTypedTextChunk("case");
2107 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2108 Builder.AddPlaceholderChunk("expression");
2109 Builder.AddChunk(CodeCompletionString::CK_Colon);
2110 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002111
2112 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002113 Builder.AddTypedTextChunk("default");
2114 Builder.AddChunk(CodeCompletionString::CK_Colon);
2115 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002116 }
2117
Douglas Gregorf64acca2010-05-25 21:41:55 +00002118 if (Results.includeCodePatterns()) {
2119 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002120 Builder.AddTypedTextChunk("while");
2121 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002122 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002123 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002124 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002125 Builder.AddPlaceholderChunk("expression");
2126 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2127 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2128 Builder.AddPlaceholderChunk("statements");
2129 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2130 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2131 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002132
2133 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002134 Builder.AddTypedTextChunk("do");
2135 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2136 Builder.AddPlaceholderChunk("statements");
2137 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2138 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2139 Builder.AddTextChunk("while");
2140 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2141 Builder.AddPlaceholderChunk("expression");
2142 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2143 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002144
Douglas Gregorf64acca2010-05-25 21:41:55 +00002145 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002146 Builder.AddTypedTextChunk("for");
2147 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002148 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002149 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002150 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002151 Builder.AddPlaceholderChunk("init-expression");
2152 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2153 Builder.AddPlaceholderChunk("condition");
2154 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2155 Builder.AddPlaceholderChunk("inc-expression");
2156 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2157 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2158 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2159 Builder.AddPlaceholderChunk("statements");
2160 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2161 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2162 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002163 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002164
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002165 if (S->getContinueParent()) {
2166 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002167 Builder.AddTypedTextChunk("continue");
2168 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002169 }
2170
2171 if (S->getBreakParent()) {
2172 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002173 Builder.AddTypedTextChunk("break");
2174 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002175 }
2176
2177 // "return expression ;" or "return ;", depending on whether we
2178 // know the function is void or not.
2179 bool isVoid = false;
Fangrui Song050229d2018-11-24 00:14:31 +00002180 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00002181 isVoid = Function->getReturnType()->isVoidType();
Fangrui Song050229d2018-11-24 00:14:31 +00002182 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00002183 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002184 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002185 !SemaRef.getCurBlock()->ReturnType.isNull())
2186 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002187 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00002188 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002189 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2190 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00002191 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002192 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002193
Douglas Gregorf4c33342010-05-28 00:22:41 +00002194 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002195 Builder.AddTypedTextChunk("goto");
2196 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2197 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002198 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002199
Douglas Gregorf4c33342010-05-28 00:22:41 +00002200 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002201 Builder.AddTypedTextChunk("using");
2202 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2203 Builder.AddTextChunk("namespace");
2204 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2205 Builder.AddPlaceholderChunk("identifier");
2206 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002207
2208 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002209 }
Fangrui Song050229d2018-11-24 00:14:31 +00002210 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002211
2212 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002213 case Sema::PCC_ForInit:
2214 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002215 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002216 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002217 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002218
Douglas Gregor5e35d592010-09-14 23:59:36 +00002219 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002220 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002221 CCC == Sema::PCC_ParenthesizedExpression) {
2222 // (__bridge <type>)<expression>
2223 Builder.AddTypedTextChunk("__bridge");
2224 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2225 Builder.AddPlaceholderChunk("type");
2226 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2227 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002228 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002229
2230 // (__bridge_transfer <Objective-C type>)<expression>
2231 Builder.AddTypedTextChunk("__bridge_transfer");
2232 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2233 Builder.AddPlaceholderChunk("Objective-C type");
2234 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2235 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002236 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002237
2238 // (__bridge_retained <CF type>)<expression>
2239 Builder.AddTypedTextChunk("__bridge_retained");
2240 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2241 Builder.AddPlaceholderChunk("CF type");
2242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2243 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002244 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002245 }
2246 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002247 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002248
John McCallfaf5fb42010-08-26 23:41:50 +00002249 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002250 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002251 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002252 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002253
Douglas Gregore5c79d52011-10-18 21:20:17 +00002254 // true
2255 Builder.AddResultTypeChunk("bool");
2256 Builder.AddTypedTextChunk("true");
2257 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002258
Douglas Gregore5c79d52011-10-18 21:20:17 +00002259 // false
2260 Builder.AddResultTypeChunk("bool");
2261 Builder.AddTypedTextChunk("false");
2262 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002263
David Blaikiebbafb8a2012-03-11 07:00:24 +00002264 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002265 // dynamic_cast < type-id > ( expression )
2266 Builder.AddTypedTextChunk("dynamic_cast");
2267 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2268 Builder.AddPlaceholderChunk("type");
2269 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2270 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2271 Builder.AddPlaceholderChunk("expression");
2272 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002273 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002274 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002275
Douglas Gregorf4c33342010-05-28 00:22:41 +00002276 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002277 Builder.AddTypedTextChunk("static_cast");
2278 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2279 Builder.AddPlaceholderChunk("type");
2280 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2281 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2282 Builder.AddPlaceholderChunk("expression");
2283 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002284 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002285
Douglas Gregorf4c33342010-05-28 00:22:41 +00002286 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002287 Builder.AddTypedTextChunk("reinterpret_cast");
2288 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2289 Builder.AddPlaceholderChunk("type");
2290 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2291 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2292 Builder.AddPlaceholderChunk("expression");
2293 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002294 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002295
Douglas Gregorf4c33342010-05-28 00:22:41 +00002296 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002297 Builder.AddTypedTextChunk("const_cast");
2298 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2299 Builder.AddPlaceholderChunk("type");
2300 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2301 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2302 Builder.AddPlaceholderChunk("expression");
2303 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002304 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002305
David Blaikiebbafb8a2012-03-11 07:00:24 +00002306 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002307 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002308 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002309 Builder.AddTypedTextChunk("typeid");
2310 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2311 Builder.AddPlaceholderChunk("expression-or-type");
2312 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002313 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002314 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002315
Douglas Gregorf4c33342010-05-28 00:22:41 +00002316 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002317 Builder.AddTypedTextChunk("new");
2318 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2319 Builder.AddPlaceholderChunk("type");
2320 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2321 Builder.AddPlaceholderChunk("expressions");
2322 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002323 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002324
Douglas Gregorf4c33342010-05-28 00:22:41 +00002325 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002326 Builder.AddTypedTextChunk("new");
2327 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2328 Builder.AddPlaceholderChunk("type");
2329 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2330 Builder.AddPlaceholderChunk("size");
2331 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
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 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002338 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002339 Builder.AddTypedTextChunk("delete");
2340 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2341 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002342 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002343
Douglas Gregorf4c33342010-05-28 00:22:41 +00002344 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002345 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002346 Builder.AddTypedTextChunk("delete");
2347 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2348 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2349 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2350 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2351 Builder.AddPlaceholderChunk("expression");
2352 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002353
David Blaikiebbafb8a2012-03-11 07:00:24 +00002354 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002355 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002356 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002357 Builder.AddTypedTextChunk("throw");
2358 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2359 Builder.AddPlaceholderChunk("expression");
2360 Results.AddResult(Result(Builder.TakeString()));
2361 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002362
Douglas Gregora2db7932010-05-26 22:00:08 +00002363 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002364
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002365 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002366 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002367 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002368 Builder.AddTypedTextChunk("nullptr");
2369 Results.AddResult(Result(Builder.TakeString()));
2370
2371 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002372 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002373 Builder.AddTypedTextChunk("alignof");
2374 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2375 Builder.AddPlaceholderChunk("type");
2376 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2377 Results.AddResult(Result(Builder.TakeString()));
2378
2379 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002380 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002381 Builder.AddTypedTextChunk("noexcept");
2382 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2383 Builder.AddPlaceholderChunk("expression");
2384 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2385 Results.AddResult(Result(Builder.TakeString()));
2386
2387 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002388 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002389 Builder.AddTypedTextChunk("sizeof...");
2390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2391 Builder.AddPlaceholderChunk("parameter-pack");
2392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2393 Results.AddResult(Result(Builder.TakeString()));
2394 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002395 }
2396
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002397 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002398 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002399 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2400 // The interface can be NULL.
2401 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002402 if (ID->getSuperClass()) {
2403 std::string SuperType;
2404 SuperType = ID->getSuperClass()->getNameAsString();
2405 if (Method->isInstanceMethod())
2406 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002407
Douglas Gregore5c79d52011-10-18 21:20:17 +00002408 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2409 Builder.AddTypedTextChunk("super");
2410 Results.AddResult(Result(Builder.TakeString()));
2411 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002412 }
2413
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002414 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002415 }
2416
Jordan Rose58d54722012-06-30 21:33:57 +00002417 if (SemaRef.getLangOpts().C11) {
2418 // _Alignof
2419 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002420 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002421 Builder.AddTypedTextChunk("alignof");
2422 else
2423 Builder.AddTypedTextChunk("_Alignof");
2424 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2425 Builder.AddPlaceholderChunk("type");
2426 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2427 Results.AddResult(Result(Builder.TakeString()));
2428 }
2429
Douglas Gregorf4c33342010-05-28 00:22:41 +00002430 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002431 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002432 Builder.AddTypedTextChunk("sizeof");
2433 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2434 Builder.AddPlaceholderChunk("expression-or-type");
2435 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2436 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002437 break;
2438 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002439
John McCallfaf5fb42010-08-26 23:41:50 +00002440 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002441 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002442 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002443 }
2444
David Blaikiebbafb8a2012-03-11 07:00:24 +00002445 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2446 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002447
David Blaikiebbafb8a2012-03-11 07:00:24 +00002448 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002449 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002450}
2451
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002452/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002453/// type chunk.
2454static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002455 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002456 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002457 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002458 if (!ND)
2459 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002460
2461 // Skip constructors and conversion functions, which have their return types
2462 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002463 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002464 return;
2465
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002466 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002467 QualType T;
2468 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002469 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002470 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002471 if (!BaseType.isNull())
2472 T = Method->getSendResultType(BaseType);
2473 else
2474 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002475 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002476 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002477 T = clang::TypeName::getFullyQualifiedType(T, Context);
2478 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002479 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002480 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002481 if (!BaseType.isNull())
2482 T = Ivar->getUsageType(BaseType);
2483 else
2484 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002485 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002486 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002487 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002488 if (!BaseType.isNull())
2489 T = Property->getUsageType(BaseType);
2490 else
2491 T = Property->getType();
2492 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002493
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002494 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2495 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002496
Fangrui Song050229d2018-11-24 00:14:31 +00002497 Result.AddResultTypeChunk(
2498 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002499}
2500
Richard Smith20e883e2015-04-29 23:20:19 +00002501static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002502 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002503 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002504 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2505 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002506 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002507 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002508 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002509 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002510 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002511 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002512 }
2513}
2514
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002515static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002516 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002517 std::string Result;
2518 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002519 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002520 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002521 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002522 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002523 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002524 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002525 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002526 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002527 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002528 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002529 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002530 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2531 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2532 switch (*nullability) {
2533 case NullabilityKind::NonNull:
2534 Result += "nonnull ";
2535 break;
2536
2537 case NullabilityKind::Nullable:
2538 Result += "nullable ";
2539 break;
2540
2541 case NullabilityKind::Unspecified:
2542 Result += "null_unspecified ";
2543 break;
2544 }
2545 }
2546 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002547 return Result;
2548}
2549
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002550/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002551/// block placeholder.
2552///
2553/// This function ignores things like typedefs and qualifiers in order to
2554/// present the most relevant and accurate block placeholders in code completion
2555/// results.
2556static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2557 FunctionTypeLoc &Block,
2558 FunctionProtoTypeLoc &BlockProto,
2559 bool SuppressBlock = false) {
2560 if (!TSInfo)
2561 return;
2562 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2563 while (true) {
2564 // Look through typedefs.
2565 if (!SuppressBlock) {
2566 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2567 if (TypeSourceInfo *InnerTSInfo =
2568 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2569 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2570 continue;
2571 }
2572 }
2573
2574 // Look through qualified types
2575 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2576 TL = QualifiedTL.getUnqualifiedLoc();
2577 continue;
2578 }
2579
2580 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2581 TL = AttrTL.getModifiedLoc();
2582 continue;
2583 }
2584 }
2585
2586 // Try to get the function prototype behind the block pointer type,
2587 // then we're done.
2588 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2589 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2590 Block = TL.getAs<FunctionTypeLoc>();
2591 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2592 }
2593 break;
2594 }
2595}
2596
Alex Lorenz920ae142016-10-18 10:38:58 +00002597static std::string
2598formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2599 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002600 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002601 bool SuppressBlock = false,
2602 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2603
Fangrui Song050229d2018-11-24 00:14:31 +00002604static std::string
2605FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2606 bool SuppressName = false, bool SuppressBlock = false,
2607 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002608 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2609 if (Param->getType()->isDependentType() ||
2610 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002611 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002612 // containing that parameter's type.
2613 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002614
Douglas Gregor981a0c42010-08-29 19:47:46 +00002615 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002616 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002617
Douglas Gregor86b42682015-06-19 18:27:52 +00002618 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002619 if (ObjCSubsts)
2620 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2621 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002622 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002623 Result =
2624 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002625 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002626 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002627 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002628 } else {
2629 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002630 }
2631 return Result;
2632 }
Alex Lorenza1951202016-10-18 10:35:27 +00002633
Douglas Gregore90dd002010-08-24 16:15:59 +00002634 // The argument for a block pointer parameter is a block literal with
2635 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002636 FunctionTypeLoc Block;
2637 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002638 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2639 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002640 // Try to retrieve the block type information from the property if this is a
2641 // parameter in a setter.
2642 if (!Block && ObjCMethodParam &&
2643 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2644 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2645 ->findPropertyDecl(/*CheckOverrides=*/false))
2646 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2647 SuppressBlock);
2648 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002649
2650 if (!Block) {
2651 // We were unable to find a FunctionProtoTypeLoc with parameter names
2652 // for the block; just use the parameter type as a placeholder.
2653 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002654 if (!ObjCMethodParam && Param->getIdentifier())
2655 Result = Param->getIdentifier()->getName();
2656
Douglas Gregor86b42682015-06-19 18:27:52 +00002657 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002658
Douglas Gregore90dd002010-08-24 16:15:59 +00002659 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002660 Result = Type.getAsString(Policy);
2661 std::string Quals =
2662 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2663 if (!Quals.empty())
2664 Result = "(" + Quals + " " + Result + ")";
2665 if (Result.back() != ')')
2666 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002667 if (Param->getIdentifier())
2668 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002669 } else {
2670 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002671 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002672
Douglas Gregore90dd002010-08-24 16:15:59 +00002673 return Result;
2674 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002675
Douglas Gregore90dd002010-08-24 16:15:59 +00002676 // We have the function prototype behind the block pointer type, as it was
2677 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002678 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2679 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002680 ObjCSubsts);
2681}
2682
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002683/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002684/// declaration.
2685///
2686/// \param BlockDecl A declaration with an Objective-C block type.
2687///
2688/// \param Block The most relevant type location for that block type.
2689///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002690/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002691/// declaration is included in the resulting string.
2692static std::string
2693formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2694 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002695 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002696 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002697 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002698 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002699 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002700 ResultType =
2701 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2702 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002703 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002704 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002705
2706 // Format the parameter list.
2707 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002708 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002709 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002710 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002711 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002712 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002713 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002714 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002715 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002716 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002717 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002718 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002719 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002720 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002721
David Blaikie6adc78e2013-02-18 22:06:02 +00002722 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002723 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002724 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002725 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002726 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002727
Douglas Gregord793e7c2011-10-18 04:23:19 +00002728 if (SuppressBlock) {
2729 // Format as a parameter.
2730 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002731 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002732 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002733 Result += ")";
2734 Result += Params;
2735 } else {
2736 // Format as a block literal argument.
2737 Result = '^' + Result;
2738 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002739
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002740 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002741 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002742 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002743
Douglas Gregore90dd002010-08-24 16:15:59 +00002744 return Result;
2745}
2746
Erik Verbruggen11338c52017-07-19 10:45:40 +00002747static std::string GetDefaultValueString(const ParmVarDecl *Param,
2748 const SourceManager &SM,
2749 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002750 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002751 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2752 bool Invalid = CharSrcRange.isInvalid();
2753 if (Invalid)
2754 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002755 StringRef srcText =
2756 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002757 if (Invalid)
2758 return "";
2759
2760 if (srcText.empty() || srcText == "=") {
2761 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002762 // This happens if the code is incorrect (for example class is forward
2763 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002764 return "";
2765 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002766 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002767 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2768 // this value always has (or always does not have) '=' in front of it
2769 if (DefValue.at(0) != '=') {
2770 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002771 // Lexer returns built-in types values without '=' and user-defined types
2772 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002773 return " = " + DefValue;
2774 }
2775 return " " + DefValue;
2776}
2777
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002778/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002779static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002780 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002781 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002782 CodeCompletionBuilder &Result,
2783 unsigned Start = 0,
2784 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002785 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002786
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002787 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002788 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002789
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002790 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002791 // When we see an optional default argument, put that argument and
2792 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002793 CodeCompletionBuilder Opt(Result.getAllocator(),
2794 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002795 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002796 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002797 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002798 Result.AddOptionalChunk(Opt.TakeString());
2799 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002800 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002801
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002802 if (FirstParameter)
2803 FirstParameter = false;
2804 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002805 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002806
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002807 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002808
Douglas Gregor3545ff42009-09-21 16:56:56 +00002809 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002810 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002811 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002812 PlaceholderStr +=
2813 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002814
Douglas Gregor400f5972010-08-31 05:13:43 +00002815 if (Function->isVariadic() && P == N - 1)
2816 PlaceholderStr += ", ...";
2817
Douglas Gregor3545ff42009-09-21 16:56:56 +00002818 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002819 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002820 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002821 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002822
Fangrui Song050229d2018-11-24 00:14:31 +00002823 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002824 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002825 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002826 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002827
Richard Smith20e883e2015-04-29 23:20:19 +00002828 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002829 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002830}
2831
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002832/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002833static void AddTemplateParameterChunks(
2834 ASTContext &Context, const PrintingPolicy &Policy,
2835 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2836 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002837 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002838
2839 // Prefer to take the template parameter names from the first declaration of
2840 // the template.
2841 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2842
Douglas Gregor3545ff42009-09-21 16:56:56 +00002843 TemplateParameterList *Params = Template->getTemplateParameters();
2844 TemplateParameterList::iterator PEnd = Params->end();
2845 if (MaxParameters)
2846 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002847 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2848 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002849 bool HasDefaultArg = false;
2850 std::string PlaceholderStr;
2851 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2852 if (TTP->wasDeclaredWithTypename())
2853 PlaceholderStr = "typename";
2854 else
2855 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002856
Douglas Gregor3545ff42009-09-21 16:56:56 +00002857 if (TTP->getIdentifier()) {
2858 PlaceholderStr += ' ';
2859 PlaceholderStr += TTP->getIdentifier()->getName();
2860 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002861
Douglas Gregor3545ff42009-09-21 16:56:56 +00002862 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002863 } else if (NonTypeTemplateParmDecl *NTTP =
2864 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002865 if (NTTP->getIdentifier())
2866 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002867 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002868 HasDefaultArg = NTTP->hasDefaultArgument();
2869 } else {
2870 assert(isa<TemplateTemplateParmDecl>(*P));
2871 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002872
Douglas Gregor3545ff42009-09-21 16:56:56 +00002873 // Since putting the template argument list into the placeholder would
2874 // be very, very long, we just use an abbreviation.
2875 PlaceholderStr = "template<...> class";
2876 if (TTP->getIdentifier()) {
2877 PlaceholderStr += ' ';
2878 PlaceholderStr += TTP->getIdentifier()->getName();
2879 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002880
Douglas Gregor3545ff42009-09-21 16:56:56 +00002881 HasDefaultArg = TTP->hasDefaultArgument();
2882 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002883
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002884 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002885 // When we see an optional default argument, put that argument and
2886 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002887 CodeCompletionBuilder Opt(Result.getAllocator(),
2888 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002889 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002890 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002891 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002892 P - Params->begin(), true);
2893 Result.AddOptionalChunk(Opt.TakeString());
2894 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002895 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002896
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002897 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002898
Douglas Gregor3545ff42009-09-21 16:56:56 +00002899 if (FirstParameter)
2900 FirstParameter = false;
2901 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002902 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002903
Douglas Gregor3545ff42009-09-21 16:56:56 +00002904 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002905 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002906 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002907 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002908}
2909
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002910/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002911/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002912static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2913 NestedNameSpecifier *Qualifier,
2914 bool QualifierIsInformative,
2915 ASTContext &Context,
2916 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002917 if (!Qualifier)
2918 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002919
Douglas Gregorf2510672009-09-21 19:57:38 +00002920 std::string PrintedNNS;
2921 {
2922 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002923 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002924 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002925 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002926 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002927 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002928 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002929}
2930
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002931static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002932AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002933 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002934 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002935 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00002936 return;
2937
Douglas Gregor304f9b02011-02-01 21:15:40 +00002938 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002939
Douglas Gregor304f9b02011-02-01 21:15:40 +00002940 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002941 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002942 Result.AddInformativeChunk(" const");
2943 return;
2944 }
2945
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002946 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002947 Result.AddInformativeChunk(" volatile");
2948 return;
2949 }
2950
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002951 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002952 Result.AddInformativeChunk(" restrict");
2953 return;
2954 }
2955
2956 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002957 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002958 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002959 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002960 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002961 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002962 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002963 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002964 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002965}
2966
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002967/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002968static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002969 const NamedDecl *ND,
2970 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002971 DeclarationName Name = ND->getDeclName();
2972 if (!Name)
2973 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002974
Douglas Gregor0212fd72010-09-21 16:06:22 +00002975 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002976 case DeclarationName::CXXOperatorName: {
2977 const char *OperatorName = nullptr;
2978 switch (Name.getCXXOverloadedOperator()) {
2979 case OO_None:
2980 case OO_Conditional:
2981 case NUM_OVERLOADED_OPERATORS:
2982 OperatorName = "operator";
2983 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002984
Fangrui Song050229d2018-11-24 00:14:31 +00002985#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
2986 case OO_##Name: \
2987 OperatorName = "operator" Spelling; \
2988 break;
2989#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00002990#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002991
Fangrui Song050229d2018-11-24 00:14:31 +00002992 case OO_New:
2993 OperatorName = "operator new";
2994 break;
2995 case OO_Delete:
2996 OperatorName = "operator delete";
2997 break;
2998 case OO_Array_New:
2999 OperatorName = "operator new[]";
3000 break;
3001 case OO_Array_Delete:
3002 OperatorName = "operator delete[]";
3003 break;
3004 case OO_Call:
3005 OperatorName = "operator()";
3006 break;
3007 case OO_Subscript:
3008 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003009 break;
3010 }
Fangrui Song050229d2018-11-24 00:14:31 +00003011 Result.AddTypedTextChunk(OperatorName);
3012 break;
3013 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003014
Douglas Gregor0212fd72010-09-21 16:06:22 +00003015 case DeclarationName::Identifier:
3016 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003017 case DeclarationName::CXXDestructorName:
3018 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003019 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003020 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003021 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003022
Richard Smith35845152017-02-07 01:37:30 +00003023 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003024 case DeclarationName::CXXUsingDirective:
3025 case DeclarationName::ObjCZeroArgSelector:
3026 case DeclarationName::ObjCOneArgSelector:
3027 case DeclarationName::ObjCMultiArgSelector:
3028 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003029
Douglas Gregor0212fd72010-09-21 16:06:22 +00003030 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003031 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003032 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003033 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003034 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003035 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003036 Record = InjectedTy->getDecl();
3037 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003038 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003039 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003040 break;
3041 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003042
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003043 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003044 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003045 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003046 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003047 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003048 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003049 }
3050 break;
3051 }
3052 }
3053}
3054
Fangrui Song050229d2018-11-24 00:14:31 +00003055CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3056 Sema &S, const CodeCompletionContext &CCContext,
3057 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3058 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003059 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3060 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003061}
3062
Eric Liu00f43c92018-07-06 09:43:57 +00003063CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3064 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3065 CodeCompletionTUInfo &CCTUInfo) {
3066 assert(Kind == RK_Macro);
3067 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3068 const MacroInfo *MI = PP.getMacroInfo(Macro);
3069 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3070
3071 if (!MI || !MI->isFunctionLike())
3072 return Result.TakeString();
3073
3074 // Format a function-like macro with placeholders for the arguments.
3075 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3076 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3077
3078 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3079 if (MI->isC99Varargs()) {
3080 --AEnd;
3081
3082 if (A == AEnd) {
3083 Result.AddPlaceholderChunk("...");
3084 }
3085 }
3086
3087 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3088 if (A != MI->param_begin())
3089 Result.AddChunk(CodeCompletionString::CK_Comma);
3090
3091 if (MI->isVariadic() && (A + 1) == AEnd) {
3092 SmallString<32> Arg = (*A)->getName();
3093 if (MI->isC99Varargs())
3094 Arg += ", ...";
3095 else
3096 Arg += "...";
3097 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3098 break;
3099 }
3100
3101 // Non-variadic macros are simple.
3102 Result.AddPlaceholderChunk(
3103 Result.getAllocator().CopyString((*A)->getName()));
3104 }
3105 Result.AddChunk(CodeCompletionString::CK_RightParen);
3106 return Result.TakeString();
3107}
3108
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003109/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003110/// result.
3111///
3112/// \returns Either a new, heap-allocated code completion string describing
3113/// how to use this result, or NULL to indicate that the string or name of the
3114/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003115CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3116 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3117 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3118 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003119 if (Kind == RK_Macro)
3120 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3121
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003122 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003123
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003124 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003125 if (Kind == RK_Pattern) {
3126 Pattern->Priority = Priority;
3127 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003128
Douglas Gregor78254c82012-03-27 23:34:16 +00003129 if (Declaration) {
3130 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003131 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003132 if (const RawComment *RC =
3133 getPatternCompletionComment(Ctx, Declaration)) {
3134 Result.addBriefComment(RC->getBriefText(Ctx));
3135 Pattern->BriefComment = Result.getBriefComment();
3136 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003137 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003138
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003139 return Pattern;
3140 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003141
Douglas Gregorf09935f2009-12-01 05:55:20 +00003142 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003143 Result.AddTypedTextChunk(Keyword);
3144 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003145 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003146 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003147 return createCodeCompletionStringForDecl(
3148 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003149}
3150
3151CodeCompletionString *
3152CodeCompletionResult::createCodeCompletionStringForOverride(
3153 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3154 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3155 PrintingPolicy &Policy) {
3156 std::string OverrideSignature;
3157 llvm::raw_string_ostream OS(OverrideSignature);
3158 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3159 /*IncludeBriefComments=*/false,
3160 CCContext, Policy);
3161 printOverrideString(OS, CCS);
3162 OS << " override";
3163 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
3164 return Result.TakeString();
3165}
3166
3167CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3168 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3169 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3170 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003171 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003172 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003173
3174 if (IncludeBriefComments) {
3175 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003176 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003177 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003178 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003179 }
3180
Douglas Gregor9eb77012009-11-07 00:00:49 +00003181 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003182 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003183 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003184 Result.AddTextChunk("::");
3185 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003186 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003187
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003188 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3189 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003190
Douglas Gregorc3425b12015-07-07 06:20:19 +00003191 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003192
Fangrui Song050229d2018-11-24 00:14:31 +00003193 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003194 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003195 Ctx, Policy);
3196 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003197 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003198 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003199 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003200 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003201 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003202 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003203
Fangrui Song050229d2018-11-24 00:14:31 +00003204 if (const FunctionTemplateDecl *FunTmpl =
3205 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003206 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003207 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003208 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003209 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003210
Douglas Gregor3545ff42009-09-21 16:56:56 +00003211 // Figure out which template parameters are deduced (or have default
3212 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003213 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003214 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003215 unsigned LastDeducibleArgument;
3216 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3217 --LastDeducibleArgument) {
3218 if (!Deduced[LastDeducibleArgument - 1]) {
3219 // C++0x: Figure out if the template argument has a default. If so,
3220 // the user doesn't need to type this argument.
3221 // FIXME: We need to abstract template parameters better!
3222 bool HasDefaultArg = false;
3223 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003224 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003225 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3226 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003227 else if (NonTypeTemplateParmDecl *NTTP =
3228 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003229 HasDefaultArg = NTTP->hasDefaultArgument();
3230 else {
3231 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003232 HasDefaultArg =
3233 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003234 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003235
Douglas Gregor3545ff42009-09-21 16:56:56 +00003236 if (!HasDefaultArg)
3237 break;
3238 }
3239 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003240
Douglas Gregor3545ff42009-09-21 16:56:56 +00003241 if (LastDeducibleArgument) {
3242 // Some of the function template arguments cannot be deduced from a
3243 // function call, so we introduce an explicit template argument list
3244 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003245 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003246 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003247 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003248 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003249 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003250
Douglas Gregor3545ff42009-09-21 16:56:56 +00003251 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003252 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003253 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003254 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003255 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003256 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003257 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003258
Fangrui Song050229d2018-11-24 00:14:31 +00003259 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003260 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003261 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003262 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003263 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003264 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003265 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003266 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003267 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003268 }
Fangrui Song050229d2018-11-24 00:14:31 +00003269 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003270 Selector Sel = Method->getSelector();
3271 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003272 Result.AddTypedTextChunk(
3273 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003274 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003275 }
3276
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003277 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003278 SelName += ':';
3279 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003280 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003281 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003282 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003283
Douglas Gregor1b605f72009-11-19 01:08:35 +00003284 // If there is only one parameter, and we're past it, add an empty
3285 // typed-text chunk since there is nothing to type.
3286 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003287 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003288 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003289 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003290 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003291 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003292 P != PEnd; (void)++P, ++Idx) {
3293 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003294 std::string Keyword;
3295 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003296 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003297 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003298 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003299 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003300 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003301 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003302 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003303 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003304 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003305
Douglas Gregor1b605f72009-11-19 01:08:35 +00003306 // If we're before the starting parameter, skip the placeholder.
3307 if (Idx < StartParameter)
3308 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003309
3310 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003311 QualType ParamType = (*P)->getType();
3312 Optional<ArrayRef<QualType>> ObjCSubsts;
3313 if (!CCContext.getBaseType().isNull())
3314 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3315
3316 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3317 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003318 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003319 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003320 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003321 ParamType = ParamType.substObjCTypeArgs(
3322 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003323 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003324 ParamType);
3325 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003326 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003327 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003328 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003329 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003330
Douglas Gregor400f5972010-08-31 05:13:43 +00003331 if (Method->isVariadic() && (P + 1) == PEnd)
3332 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003333
Douglas Gregor95887f92010-07-08 23:20:03 +00003334 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003335 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003336 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003337 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003338 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003339 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003340 }
3341
Douglas Gregor04c5f972009-12-23 00:21:46 +00003342 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003343 if (Method->param_size() == 0) {
3344 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003345 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003346 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003347 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003348 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003349 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003350 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003351
Richard Smith20e883e2015-04-29 23:20:19 +00003352 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003353 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003354
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003355 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003356 }
3357
Douglas Gregorf09935f2009-12-01 05:55:20 +00003358 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003359 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003360 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003361
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003362 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003363 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003364 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003365}
3366
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003367const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3368 const NamedDecl *ND) {
3369 if (!ND)
3370 return nullptr;
3371 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3372 return RC;
3373
3374 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003375 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003376 if (!M)
3377 return nullptr;
3378 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3379 if (!PDecl)
3380 return nullptr;
3381
3382 return Ctx.getRawCommentForAnyRedecl(PDecl);
3383}
3384
3385const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3386 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003387 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003388 if (!M || !M->isPropertyAccessor())
3389 return nullptr;
3390
3391 // Provide code completion comment for self.GetterName where
3392 // GetterName is the getter method for a property with name
3393 // different from the property name (declared via a property
3394 // getter attribute.
3395 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3396 if (!PDecl)
3397 return nullptr;
3398 if (PDecl->getGetterName() == M->getSelector() &&
3399 PDecl->getIdentifier() != M->getIdentifier()) {
3400 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3401 return RC;
3402 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3403 return RC;
3404 }
3405 return nullptr;
3406}
3407
3408const RawComment *clang::getParameterComment(
3409 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003410 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003411 auto FDecl = Result.getFunction();
3412 if (!FDecl)
3413 return nullptr;
3414 if (ArgIndex < FDecl->getNumParams())
3415 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3416 return nullptr;
3417}
3418
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003419/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003420/// string.
3421static void AddOverloadParameterChunks(ASTContext &Context,
3422 const PrintingPolicy &Policy,
3423 const FunctionDecl *Function,
3424 const FunctionProtoType *Prototype,
3425 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003426 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003427 bool InOptional = false) {
3428 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003429 unsigned NumParams =
3430 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003431
3432 for (unsigned P = Start; P != NumParams; ++P) {
3433 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3434 // When we see an optional default argument, put that argument and
3435 // the remaining default arguments into a new, optional string.
3436 CodeCompletionBuilder Opt(Result.getAllocator(),
3437 Result.getCodeCompletionTUInfo());
3438 if (!FirstParameter)
3439 Opt.AddChunk(CodeCompletionString::CK_Comma);
3440 // Optional sections are nested.
3441 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3442 CurrentArg, P, /*InOptional=*/true);
3443 Result.AddOptionalChunk(Opt.TakeString());
3444 return;
3445 }
3446
3447 if (FirstParameter)
3448 FirstParameter = false;
3449 else
3450 Result.AddChunk(CodeCompletionString::CK_Comma);
3451
3452 InOptional = false;
3453
3454 // Format the placeholder string.
3455 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003456 if (Function) {
3457 const ParmVarDecl *Param = Function->getParamDecl(P);
3458 Placeholder = FormatFunctionParameter(Policy, Param);
3459 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003460 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3461 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003462 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003463 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003464 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003465
3466 if (P == CurrentArg)
3467 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003468 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003469 else
3470 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3471 }
3472
3473 if (Prototype && Prototype->isVariadic()) {
3474 CodeCompletionBuilder Opt(Result.getAllocator(),
3475 Result.getCodeCompletionTUInfo());
3476 if (!FirstParameter)
3477 Opt.AddChunk(CodeCompletionString::CK_Comma);
3478
3479 if (CurrentArg < NumParams)
3480 Opt.AddPlaceholderChunk("...");
3481 else
3482 Opt.AddCurrentParameterChunk("...");
3483
3484 Result.AddOptionalChunk(Opt.TakeString());
3485 }
3486}
3487
Douglas Gregorf0f51982009-09-23 00:34:09 +00003488CodeCompletionString *
3489CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003490 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3491 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003492 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003493
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003494 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003495 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3496 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003497 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003498 const FunctionProtoType *Proto =
3499 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003500 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003501 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003502 // highlighted ellipsis.
3503 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003504 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003505 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003506 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3507 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3508 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003509 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003510 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003511
3512 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003513 if (IncludeBriefComments) {
3514 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003515 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003516 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003517 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003518 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003519 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003520 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003521 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003522 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003523 }
Alp Toker314cc812014-01-25 16:55:45 +00003524
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003525 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003526 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3527 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003528 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003529
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003530 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003531}
3532
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003533unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003534 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003535 bool PreferredTypeIsPointer) {
3536 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003537
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003538 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003539 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003540 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003541 Priority = CCP_Constant;
3542 if (PreferredTypeIsPointer)
3543 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003544 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003545 // Treat "YES", "NO", "true", and "false" as constants.
3546 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3547 MacroName.equals("true") || MacroName.equals("false"))
3548 Priority = CCP_Constant;
3549 // Treat "bool" as a type.
3550 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003551 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003552
Douglas Gregor6e240332010-08-16 16:18:59 +00003553 return Priority;
3554}
3555
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003556CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003557 if (!D)
3558 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003559
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003560 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003561 case Decl::Enum:
3562 return CXCursor_EnumDecl;
3563 case Decl::EnumConstant:
3564 return CXCursor_EnumConstantDecl;
3565 case Decl::Field:
3566 return CXCursor_FieldDecl;
3567 case Decl::Function:
3568 return CXCursor_FunctionDecl;
3569 case Decl::ObjCCategory:
3570 return CXCursor_ObjCCategoryDecl;
3571 case Decl::ObjCCategoryImpl:
3572 return CXCursor_ObjCCategoryImplDecl;
3573 case Decl::ObjCImplementation:
3574 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003575
Fangrui Song050229d2018-11-24 00:14:31 +00003576 case Decl::ObjCInterface:
3577 return CXCursor_ObjCInterfaceDecl;
3578 case Decl::ObjCIvar:
3579 return CXCursor_ObjCIvarDecl;
3580 case Decl::ObjCMethod:
3581 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3582 ? CXCursor_ObjCInstanceMethodDecl
3583 : CXCursor_ObjCClassMethodDecl;
3584 case Decl::CXXMethod:
3585 return CXCursor_CXXMethod;
3586 case Decl::CXXConstructor:
3587 return CXCursor_Constructor;
3588 case Decl::CXXDestructor:
3589 return CXCursor_Destructor;
3590 case Decl::CXXConversion:
3591 return CXCursor_ConversionFunction;
3592 case Decl::ObjCProperty:
3593 return CXCursor_ObjCPropertyDecl;
3594 case Decl::ObjCProtocol:
3595 return CXCursor_ObjCProtocolDecl;
3596 case Decl::ParmVar:
3597 return CXCursor_ParmDecl;
3598 case Decl::Typedef:
3599 return CXCursor_TypedefDecl;
3600 case Decl::TypeAlias:
3601 return CXCursor_TypeAliasDecl;
3602 case Decl::TypeAliasTemplate:
3603 return CXCursor_TypeAliasTemplateDecl;
3604 case Decl::Var:
3605 return CXCursor_VarDecl;
3606 case Decl::Namespace:
3607 return CXCursor_Namespace;
3608 case Decl::NamespaceAlias:
3609 return CXCursor_NamespaceAlias;
3610 case Decl::TemplateTypeParm:
3611 return CXCursor_TemplateTypeParameter;
3612 case Decl::NonTypeTemplateParm:
3613 return CXCursor_NonTypeTemplateParameter;
3614 case Decl::TemplateTemplateParm:
3615 return CXCursor_TemplateTemplateParameter;
3616 case Decl::FunctionTemplate:
3617 return CXCursor_FunctionTemplate;
3618 case Decl::ClassTemplate:
3619 return CXCursor_ClassTemplate;
3620 case Decl::AccessSpec:
3621 return CXCursor_CXXAccessSpecifier;
3622 case Decl::ClassTemplatePartialSpecialization:
3623 return CXCursor_ClassTemplatePartialSpecialization;
3624 case Decl::UsingDirective:
3625 return CXCursor_UsingDirective;
3626 case Decl::StaticAssert:
3627 return CXCursor_StaticAssert;
3628 case Decl::Friend:
3629 return CXCursor_FriendDecl;
3630 case Decl::TranslationUnit:
3631 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003632
Fangrui Song050229d2018-11-24 00:14:31 +00003633 case Decl::Using:
3634 case Decl::UnresolvedUsingValue:
3635 case Decl::UnresolvedUsingTypename:
3636 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003637
Fangrui Song050229d2018-11-24 00:14:31 +00003638 case Decl::ObjCPropertyImpl:
3639 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3640 case ObjCPropertyImplDecl::Dynamic:
3641 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003642
Fangrui Song050229d2018-11-24 00:14:31 +00003643 case ObjCPropertyImplDecl::Synthesize:
3644 return CXCursor_ObjCSynthesizeDecl;
3645 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003646 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003647
3648 case Decl::Import:
3649 return CXCursor_ModuleImportDecl;
3650
3651 case Decl::ObjCTypeParam:
3652 return CXCursor_TemplateTypeParameter;
3653
3654 default:
3655 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3656 switch (TD->getTagKind()) {
3657 case TTK_Interface: // fall through
3658 case TTK_Struct:
3659 return CXCursor_StructDecl;
3660 case TTK_Class:
3661 return CXCursor_ClassDecl;
3662 case TTK_Union:
3663 return CXCursor_UnionDecl;
3664 case TTK_Enum:
3665 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003666 }
Fangrui Song050229d2018-11-24 00:14:31 +00003667 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003668 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003669
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003670 return CXCursor_UnexposedDecl;
3671}
3672
Douglas Gregor55b037b2010-07-08 20:55:51 +00003673static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003674 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003675 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003676 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003677
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003678 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003679
Eric Liu88de9f62018-09-19 09:34:55 +00003680 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3681 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003682 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003683 auto MD = PP.getMacroDefinition(M->first);
3684 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003685 MacroInfo *MI = MD.getMacroInfo();
3686 if (MI && MI->isUsedForHeaderGuard())
3687 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003688
Eric Liud485df12018-09-05 14:59:17 +00003689 Results.AddResult(
3690 Result(M->first, MI,
3691 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3692 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003693 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003694 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003695
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003696 Results.ExitScope();
3697}
3698
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003699static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003700 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003701 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003702
Douglas Gregorce0e8562010-08-23 21:54:33 +00003703 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003704
Douglas Gregorce0e8562010-08-23 21:54:33 +00003705 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3706 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003707 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003708 Results.AddResult(Result("__func__", CCP_Constant));
3709 Results.ExitScope();
3710}
3711
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003712static void HandleCodeCompleteResults(Sema *S,
3713 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003714 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003715 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003716 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003717 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003718 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003719}
3720
Ilya Biryukov41109672018-12-13 15:36:32 +00003721static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003722mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003723 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003724 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003725 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003726
John McCallfaf5fb42010-08-26 23:41:50 +00003727 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003728 return CodeCompletionContext::CCC_ClassStructUnion;
3729
John McCallfaf5fb42010-08-26 23:41:50 +00003730 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003731 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003732
John McCallfaf5fb42010-08-26 23:41:50 +00003733 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003734 return CodeCompletionContext::CCC_ObjCImplementation;
3735
John McCallfaf5fb42010-08-26 23:41:50 +00003736 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003737 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003738
John McCallfaf5fb42010-08-26 23:41:50 +00003739 case Sema::PCC_Template:
3740 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003741 if (S.CurContext->isFileContext())
3742 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003743 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003744 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003745 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003746
John McCallfaf5fb42010-08-26 23:41:50 +00003747 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003748 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003749
John McCallfaf5fb42010-08-26 23:41:50 +00003750 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003751 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003752 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003753 return CodeCompletionContext::CCC_ParenthesizedExpression;
3754 else
3755 return CodeCompletionContext::CCC_Expression;
3756
3757 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003758 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003759 case Sema::PCC_Condition:
3760 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3761 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003762
John McCallfaf5fb42010-08-26 23:41:50 +00003763 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003764 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003765
John McCallfaf5fb42010-08-26 23:41:50 +00003766 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003767 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003768
3769 case Sema::PCC_ParenthesizedExpression:
3770 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003771
Douglas Gregor80039242011-02-15 20:33:25 +00003772 case Sema::PCC_LocalDeclarationSpecifiers:
3773 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003774 }
David Blaikie8a40f702012-01-17 06:56:22 +00003775
3776 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003777}
3778
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003779/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003780/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003781/// overridden function as well as adding new functionality.
3782///
3783/// \param S The semantic analysis object for which we are generating results.
3784///
3785/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003786/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003787static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3788 ResultBuilder &Results) {
3789 // Look through blocks.
3790 DeclContext *CurContext = S.CurContext;
3791 while (isa<BlockDecl>(CurContext))
3792 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003793
Douglas Gregorac322ec2010-08-27 21:18:54 +00003794 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3795 if (!Method || !Method->isVirtual())
3796 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003797
3798 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003799 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003800 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003801 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003802 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003803
Douglas Gregor75acd922011-09-27 23:30:47 +00003804 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003805 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003806 CodeCompletionBuilder Builder(Results.getAllocator(),
3807 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003808 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3809 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003810
Douglas Gregorac322ec2010-08-27 21:18:54 +00003811 // If we need a nested-name-specifier, add one now.
3812 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003813 NestedNameSpecifier *NNS = getRequiredQualification(
3814 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003815 if (NNS) {
3816 std::string Str;
3817 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003818 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003819 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003820 }
3821 } else if (!InContext->Equals(Overridden->getDeclContext()))
3822 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003823
Fangrui Song050229d2018-11-24 00:14:31 +00003824 Builder.AddTypedTextChunk(
3825 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003826 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003827 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003828 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003829 if (FirstParam)
3830 FirstParam = false;
3831 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003832 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003833
Aaron Ballman43b68be2014-03-07 17:50:17 +00003834 Builder.AddPlaceholderChunk(
3835 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003836 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003837 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003838 Results.AddResult(CodeCompletionResult(
3839 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3840 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003841 Results.Ignore(Overridden);
3842 }
3843}
3844
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003845void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003846 ModuleIdPath Path) {
3847 typedef CodeCompletionResult Result;
3848 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003849 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003850 CodeCompletionContext::CCC_Other);
3851 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003852
Douglas Gregor07f43572012-01-29 18:15:03 +00003853 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003854 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003855 typedef CodeCompletionResult Result;
3856 if (Path.empty()) {
3857 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003858 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003859 PP.getHeaderSearchInfo().collectAllModules(Modules);
3860 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3861 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003862 Builder.getAllocator().CopyString(Modules[I]->Name));
3863 Results.AddResult(Result(
3864 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3865 Modules[I]->isAvailable() ? CXAvailability_Available
3866 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003867 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003868 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003869 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003870 Module *Mod =
3871 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3872 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003873 // Enumerate submodules.
3874 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003875 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003876 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003877 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003878
Douglas Gregor07f43572012-01-29 18:15:03 +00003879 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003880 Builder.getAllocator().CopyString((*Sub)->Name));
3881 Results.AddResult(Result(
3882 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3883 (*Sub)->isAvailable() ? CXAvailability_Available
3884 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003885 }
3886 }
3887 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003888 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003889 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003890 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003891}
3892
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003893void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003894 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003895 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003896 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003897 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003898 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003899
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003900 // Determine how to filter results, e.g., so that the names of
3901 // values (functions, enumerators, function templates, etc.) are
3902 // only allowed where we can have an expression.
3903 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003904 case PCC_Namespace:
3905 case PCC_Class:
3906 case PCC_ObjCInterface:
3907 case PCC_ObjCImplementation:
3908 case PCC_ObjCInstanceVariableList:
3909 case PCC_Template:
3910 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003911 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003912 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003913 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3914 break;
3915
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003916 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003917 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003918 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003919 case PCC_ForInit:
3920 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003921 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003922 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3923 else
3924 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003925
David Blaikiebbafb8a2012-03-11 07:00:24 +00003926 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003927 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003928 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003929
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003930 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003931 // Unfiltered
3932 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003933 }
3934
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003935 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003936 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00003937 auto ThisType = getCurrentThisType();
3938 if (!ThisType.isNull())
3939 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003940
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003941 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003942 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003943 CodeCompleter->includeGlobals(),
3944 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003945
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003946 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003947 Results.ExitScope();
3948
Douglas Gregorce0e8562010-08-23 21:54:33 +00003949 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003950 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003951 case PCC_Expression:
3952 case PCC_Statement:
3953 case PCC_RecoveryInFunction:
3954 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003955 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003956 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003957
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003958 case PCC_Namespace:
3959 case PCC_Class:
3960 case PCC_ObjCInterface:
3961 case PCC_ObjCImplementation:
3962 case PCC_ObjCInstanceVariableList:
3963 case PCC_Template:
3964 case PCC_MemberTemplate:
3965 case PCC_ForInit:
3966 case PCC_Condition:
3967 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003968 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003969 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003970 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003971
Douglas Gregor9eb77012009-11-07 00:00:49 +00003972 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003973 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003974
Douglas Gregor50832e02010-09-20 22:39:41 +00003975 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003976 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003977}
3978
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003979static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003980 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003981 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00003982 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003983 ResultBuilder &Results);
3984
3985void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3986 bool AllowNonIdentifiers,
3987 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003988 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00003989 ResultBuilder Results(
3990 *this, CodeCompleter->getAllocator(),
3991 CodeCompleter->getCodeCompletionTUInfo(),
3992 AllowNestedNameSpecifiers
3993 // FIXME: Try to separate codepath leading here to deduce whether we
3994 // need an existing symbol or a new one.
3995 ? CodeCompletionContext::CCC_SymbolOrNewName
3996 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003997 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003998
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003999 // Type qualifiers can come after names.
4000 Results.AddResult(Result("const"));
4001 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004002 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004003 Results.AddResult(Result("restrict"));
4004
David Blaikiebbafb8a2012-03-11 07:00:24 +00004005 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004006 if (getLangOpts().CPlusPlus11 &&
4007 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4008 DS.getTypeSpecType() == DeclSpec::TST_struct))
4009 Results.AddResult("final");
4010
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004011 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004012 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004013 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004014
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004015 // Add nested-name-specifiers.
4016 if (AllowNestedNameSpecifiers) {
4017 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004018 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004019 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4020 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004021 CodeCompleter->includeGlobals(),
4022 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004023 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004024 }
4025 }
4026 Results.ExitScope();
4027
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004028 // If we're in a context where we might have an expression (rather than a
4029 // declaration), and what we've seen so far is an Objective-C type that could
4030 // be a receiver of a class message, this may be a class message send with
4031 // the initial opening bracket '[' missing. Add appropriate completions.
4032 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004033 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004034 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004035 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4036 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004037 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004038 (S->getFlags() & Scope::DeclScope) != 0 &&
4039 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004040 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4041 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004042 ParsedType T = DS.getRepAsType();
4043 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004044 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004045 }
4046
Douglas Gregor56ccce02010-08-24 04:59:56 +00004047 // Note that we intentionally suppress macro results here, since we do not
4048 // encourage using macros to produce the names of entities.
4049
Fangrui Song050229d2018-11-24 00:14:31 +00004050 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004051 Results.data(), Results.size());
4052}
4053
Douglas Gregor68762e72010-08-23 21:17:50 +00004054struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004055 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4056 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004057 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004058 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004059
Douglas Gregor68762e72010-08-23 21:17:50 +00004060 QualType PreferredType;
4061 bool IntegralConstantExpression;
4062 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004063 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004064 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004065};
4066
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004067/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004068/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004069void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004070 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004071 ResultBuilder Results(
4072 *this, CodeCompleter->getAllocator(),
4073 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004074 CodeCompletionContext(
4075 Data.IsParenthesized
4076 ? CodeCompletionContext::CCC_ParenthesizedExpression
4077 : CodeCompletionContext::CCC_Expression,
4078 Data.PreferredType));
4079 auto PCC =
4080 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004081 if (Data.ObjCCollection)
4082 Results.setFilter(&ResultBuilder::IsObjCCollection);
4083 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004084 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004085 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004086 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4087 else
4088 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004089
4090 if (!Data.PreferredType.isNull())
4091 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004092
Douglas Gregor68762e72010-08-23 21:17:50 +00004093 // Ignore any declarations that we were told that we don't care about.
4094 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4095 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004096
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004097 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004098 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004099 CodeCompleter->includeGlobals(),
4100 CodeCompleter->loadExternal());
4101
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004102 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004103 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004104 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004105
Douglas Gregor55b037b2010-07-08 20:55:51 +00004106 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00004107 if (!Data.PreferredType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00004108 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4109 Data.PreferredType->isMemberPointerType() ||
4110 Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004111
Fangrui Song050229d2018-11-24 00:14:31 +00004112 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004113 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004114 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004115
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004116 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004117 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4118 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00004119 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4120 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004121}
4122
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004123void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4124 bool IsParenthesized) {
4125 return CodeCompleteExpression(
4126 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004127}
4128
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004129void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4130 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004131 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004132 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004133 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004134 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004135}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004136
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004137/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004138/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004139typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004140
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004141/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004142static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4143 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4144 if (Interface->hasDefinition())
4145 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004146
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004147 return Interface;
4148 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004149
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004150 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4151 if (Protocol->hasDefinition())
4152 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004153
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004154 return Protocol;
4155 }
4156 return Container;
4157}
4158
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004159/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004160/// declaration \p BD.
4161static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4162 CodeCompletionBuilder &Builder,
4163 const NamedDecl *BD,
4164 const FunctionTypeLoc &BlockLoc,
4165 const FunctionProtoTypeLoc &BlockProtoLoc) {
4166 Builder.AddResultTypeChunk(
4167 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4168 Policy, Builder.getAllocator()));
4169
4170 AddTypedNameChunk(Context, Policy, BD, Builder);
4171 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4172
4173 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4174 Builder.AddPlaceholderChunk("...");
4175 } else {
4176 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4177 if (I)
4178 Builder.AddChunk(CodeCompletionString::CK_Comma);
4179
4180 // Format the placeholder string.
4181 std::string PlaceholderStr =
4182 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4183
4184 if (I == N - 1 && BlockProtoLoc &&
4185 BlockProtoLoc.getTypePtr()->isVariadic())
4186 PlaceholderStr += ", ...";
4187
4188 // Add the placeholder string.
4189 Builder.AddPlaceholderChunk(
4190 Builder.getAllocator().CopyString(PlaceholderStr));
4191 }
4192 }
4193
4194 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4195}
4196
Fangrui Song050229d2018-11-24 00:14:31 +00004197static void
4198AddObjCProperties(const CodeCompletionContext &CCContext,
4199 ObjCContainerDecl *Container, bool AllowCategories,
4200 bool AllowNullaryMethods, DeclContext *CurContext,
4201 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4202 bool IsBaseExprStatement = false,
4203 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004204 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004205
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004206 // Retrieve the definition.
4207 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004208
Douglas Gregor9291bad2009-11-18 01:29:26 +00004209 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004210 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004211 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004212 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004213
Alex Lorenzbaef8022016-11-09 13:43:18 +00004214 // FIXME: Provide block invocation completion for non-statement
4215 // expressions.
4216 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4217 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004218 Result R = Result(P, Results.getBasePriority(P), nullptr);
4219 if (!InOriginalClass)
4220 setInBaseClass(R);
4221 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004222 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004223 }
4224
4225 // Block setter and invocation completion is provided only when we are able
4226 // to find the FunctionProtoTypeLoc with parameter names for the block.
4227 FunctionTypeLoc BlockLoc;
4228 FunctionProtoTypeLoc BlockProtoLoc;
4229 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4230 BlockProtoLoc);
4231 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004232 Result R = Result(P, Results.getBasePriority(P), nullptr);
4233 if (!InOriginalClass)
4234 setInBaseClass(R);
4235 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004236 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004237 }
4238
4239 // The default completion result for block properties should be the block
4240 // invocation completion when the base expression is a statement.
4241 CodeCompletionBuilder Builder(Results.getAllocator(),
4242 Results.getCodeCompletionTUInfo());
4243 AddObjCBlockCall(Container->getASTContext(),
4244 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4245 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004246 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4247 if (!InOriginalClass)
4248 setInBaseClass(R);
4249 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004250
4251 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004252 // statement and the block property is mutable.
4253 if (!P->isReadOnly()) {
4254 CodeCompletionBuilder Builder(Results.getAllocator(),
4255 Results.getCodeCompletionTUInfo());
4256 AddResultTypeChunk(Container->getASTContext(),
4257 getCompletionPrintingPolicy(Results.getSema()), P,
4258 CCContext.getBaseType(), Builder);
4259 Builder.AddTypedTextChunk(
4260 Results.getAllocator().CopyString(P->getName()));
4261 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004262
Alex Lorenzbaef8022016-11-09 13:43:18 +00004263 std::string PlaceholderStr = formatBlockPlaceholder(
4264 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4265 BlockProtoLoc, /*SuppressBlockName=*/true);
4266 // Add the placeholder string.
4267 Builder.AddPlaceholderChunk(
4268 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004269
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004270 // When completing blocks properties that return void the default
4271 // property completion result should show up before the setter,
4272 // otherwise the setter completion should show up before the default
4273 // property completion, as we normally want to use the result of the
4274 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004275 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004276 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004277 Results.getBasePriority(P) +
4278 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4279 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004280 : -CCD_BlockPropertySetter));
4281 if (!InOriginalClass)
4282 setInBaseClass(R);
4283 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004284 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004285 };
4286
4287 if (IsClassProperty) {
4288 for (const auto *P : Container->class_properties())
4289 AddProperty(P);
4290 } else {
4291 for (const auto *P : Container->instance_properties())
4292 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004293 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004294
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004295 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004296 if (AllowNullaryMethods) {
4297 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004298 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004299 // Adds a method result
4300 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4301 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4302 if (!Name)
4303 return;
4304 if (!AddedProperties.insert(Name).second)
4305 return;
4306 CodeCompletionBuilder Builder(Results.getAllocator(),
4307 Results.getCodeCompletionTUInfo());
4308 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4309 Builder.AddTypedTextChunk(
4310 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004311 Result R = Result(Builder.TakeString(), M,
4312 CCP_MemberDeclaration + CCD_MethodAsProperty);
4313 if (!InOriginalClass)
4314 setInBaseClass(R);
4315 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004316 };
4317
4318 if (IsClassProperty) {
4319 for (const auto *M : Container->methods()) {
4320 // Gather the class method that can be used as implicit property
4321 // getters. Methods with arguments or methods that return void aren't
4322 // added to the results as they can't be used as a getter.
4323 if (!M->getSelector().isUnarySelector() ||
4324 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4325 continue;
4326 AddMethod(M);
4327 }
4328 } else {
4329 for (auto *M : Container->methods()) {
4330 if (M->getSelector().isUnarySelector())
4331 AddMethod(M);
4332 }
Douglas Gregor95147142011-05-05 15:50:42 +00004333 }
4334 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004335
Douglas Gregor9291bad2009-11-18 01:29:26 +00004336 // Add properties in referenced protocols.
4337 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004338 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004339 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004340 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004341 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004342 /*InOriginalClass*/ false);
4343 } else if (ObjCInterfaceDecl *IFace =
4344 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004345 if (AllowCategories) {
4346 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004347 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004348 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004349 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004350 IsBaseExprStatement, IsClassProperty,
4351 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004352 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004353
Douglas Gregor9291bad2009-11-18 01:29:26 +00004354 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004355 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004356 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004357 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004358 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004359 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004360
Douglas Gregor9291bad2009-11-18 01:29:26 +00004361 // Look in the superclass.
4362 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004363 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004364 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004365 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004366 /*InOriginalClass*/ false);
4367 } else if (const auto *Category =
4368 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004369 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004370 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004371 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004372 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004373 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004374 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004375 }
4376}
4377
Fangrui Song050229d2018-11-24 00:14:31 +00004378static void
4379AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
4380 Scope *S, QualType BaseType, RecordDecl *RD,
4381 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004382 // Indicate that we are performing a member access, and the cv-qualifiers
4383 // for the base object type.
4384 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4385
4386 // Access to a C/C++ class, struct, or union.
4387 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004388 std::vector<FixItHint> FixIts;
4389 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004390 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004391 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004392 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004393 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004394 /*IncludeDependentBases=*/true,
4395 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004396
4397 if (SemaRef.getLangOpts().CPlusPlus) {
4398 if (!Results.empty()) {
4399 // The "template" keyword can follow "->" or "." in the grammar.
4400 // However, we only want to suggest the template keyword if something
4401 // is dependent.
4402 bool IsDependent = BaseType->isDependentType();
4403 if (!IsDependent) {
4404 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4405 if (DeclContext *Ctx = DepScope->getEntity()) {
4406 IsDependent = Ctx->isDependentContext();
4407 break;
4408 }
4409 }
4410
4411 if (IsDependent)
4412 Results.AddResult(CodeCompletionResult("template"));
4413 }
4414 }
4415}
4416
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004417void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004418 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004419 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004420 bool IsBaseExprStatement,
4421 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004422 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004423 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004424
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004425 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4426 if (ConvertedBase.isInvalid())
4427 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004428 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4429
4430 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004431
4432 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004433 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004434 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004435 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004436
Douglas Gregor21325842011-07-07 16:03:39 +00004437 if (IsArrow) {
4438 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004439 } else {
4440 if (ConvertedBaseType->isObjCObjectPointerType() ||
4441 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004442 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004443 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004444 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4445 }
4446 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004447
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004448 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004449 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004450 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004451 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004452 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004453
Fangrui Song050229d2018-11-24 00:14:31 +00004454 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4455 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004456 if (!Base)
4457 return false;
4458
4459 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4460 if (ConvertedBase.isInvalid())
4461 return false;
4462 Base = ConvertedBase.get();
4463
4464 QualType BaseType = Base->getType();
4465
4466 if (IsArrow) {
4467 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4468 BaseType = Ptr->getPointeeType();
4469 else if (BaseType->isObjCObjectPointerType())
4470 /*Do nothing*/;
4471 else
4472 return false;
4473 }
4474
4475 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4476 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4477 Record->getDecl(),
4478 std::move(AccessOpFixIt));
4479 } else if (const auto *TST =
4480 BaseType->getAs<TemplateSpecializationType>()) {
4481 TemplateName TN = TST->getTemplateName();
4482 if (const auto *TD =
4483 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4484 CXXRecordDecl *RD = TD->getTemplatedDecl();
4485 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4486 std::move(AccessOpFixIt));
4487 }
4488 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4489 if (auto *RD = ICNT->getDecl())
4490 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4491 std::move(AccessOpFixIt));
4492 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4493 // Objective-C property reference.
4494 AddedPropertiesSet AddedProperties;
4495
4496 if (const ObjCObjectPointerType *ObjCPtr =
4497 BaseType->getAsObjCInterfacePointerType()) {
4498 // Add property results based on our interface.
4499 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4500 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4501 /*AllowNullaryMethods=*/true, CurContext,
4502 AddedProperties, Results, IsBaseExprStatement);
4503 }
4504
4505 // Add properties from the protocols in a qualified interface.
4506 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4507 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4508 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004509 IsBaseExprStatement, /*IsClassProperty*/ false,
4510 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004511 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4512 (!IsArrow && BaseType->isObjCObjectType())) {
4513 // Objective-C instance variable access.
4514 ObjCInterfaceDecl *Class = nullptr;
4515 if (const ObjCObjectPointerType *ObjCPtr =
4516 BaseType->getAs<ObjCObjectPointerType>())
4517 Class = ObjCPtr->getInterfaceDecl();
4518 else
4519 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4520
4521 // Add all ivars from this class and its superclasses.
4522 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004523 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004524 Results.setFilter(&ResultBuilder::IsObjCIvar);
4525 LookupVisibleDecls(
4526 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4527 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4528 }
4529 }
4530
4531 // FIXME: How do we cope with isa?
4532 return true;
4533 };
4534
Douglas Gregor9291bad2009-11-18 01:29:26 +00004535 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004536
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004537 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4538 if (CodeCompleter->includeFixIts()) {
4539 const CharSourceRange OpRange =
4540 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4541 CompletionSucceded |= DoCompletion(
4542 OtherOpBase, !IsArrow,
4543 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004544 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004545
Douglas Gregor9291bad2009-11-18 01:29:26 +00004546 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004547
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004548 if (!CompletionSucceded)
4549 return;
4550
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004551 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004552 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4553 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004554}
4555
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004556void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4557 IdentifierInfo &ClassName,
4558 SourceLocation ClassNameLoc,
4559 bool IsBaseExprStatement) {
4560 IdentifierInfo *ClassNamePtr = &ClassName;
4561 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4562 if (!IFace)
4563 return;
4564 CodeCompletionContext CCContext(
4565 CodeCompletionContext::CCC_ObjCPropertyAccess);
4566 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4567 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4568 &ResultBuilder::IsMember);
4569 Results.EnterNewScope();
4570 AddedPropertiesSet AddedProperties;
4571 AddObjCProperties(CCContext, IFace, true,
4572 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4573 Results, IsBaseExprStatement,
4574 /*IsClassProperty=*/true);
4575 Results.ExitScope();
4576 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4577 Results.data(), Results.size());
4578}
4579
Faisal Vali090da2d2018-01-01 18:23:28 +00004580void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004581 if (!CodeCompleter)
4582 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004583
4584 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004585 enum CodeCompletionContext::Kind ContextKind =
4586 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004587 switch ((DeclSpec::TST)TagSpec) {
4588 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004589 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004590 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004591 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004592
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004593 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004594 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004595 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004596 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004597
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004598 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004599 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004600 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004601 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004602 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004603 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004604
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004605 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004606 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004607 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004608
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004609 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4610 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004611 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004612
4613 // First pass: look for tags.
4614 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004615 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004616 CodeCompleter->includeGlobals(),
4617 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004618
Douglas Gregor39982192010-08-15 06:18:01 +00004619 if (CodeCompleter->includeGlobals()) {
4620 // Second pass: look for nested name specifiers.
4621 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004622 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4623 CodeCompleter->includeGlobals(),
4624 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004625 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004626
Douglas Gregor0ac41382010-09-23 23:01:17 +00004627 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004628 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004629}
4630
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004631static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4632 const LangOptions &LangOpts) {
4633 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4634 Results.AddResult("const");
4635 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4636 Results.AddResult("volatile");
4637 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4638 Results.AddResult("restrict");
4639 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4640 Results.AddResult("_Atomic");
4641 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4642 Results.AddResult("__unaligned");
4643}
4644
Douglas Gregor28c78432010-08-27 17:35:51 +00004645void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004646 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004647 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004648 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004649 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004650 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004651 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004652 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004653 Results.data(), Results.size());
4654}
4655
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004656void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4657 const VirtSpecifiers *VS) {
4658 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4659 CodeCompleter->getCodeCompletionTUInfo(),
4660 CodeCompletionContext::CCC_TypeQualifiers);
4661 Results.EnterNewScope();
4662 AddTypeQualifierResults(DS, Results, LangOpts);
4663 if (LangOpts.CPlusPlus11) {
4664 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004665 if (D.getContext() == DeclaratorContext::MemberContext &&
4666 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004667 if (!VS || !VS->isFinalSpecified())
4668 Results.AddResult("final");
4669 if (!VS || !VS->isOverrideSpecified())
4670 Results.AddResult("override");
4671 }
4672 }
4673 Results.ExitScope();
4674 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4675 Results.data(), Results.size());
4676}
4677
Benjamin Kramer72dae622016-02-18 15:30:24 +00004678void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4679 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4680}
4681
Douglas Gregord328d572009-09-21 18:10:23 +00004682void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004683 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004684 return;
John McCall5939b162011-08-06 07:30:58 +00004685
Richard Smithef6c43d2018-07-26 18:41:30 +00004686 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004687 // Condition expression might be invalid, do not continue in this case.
4688 if (!Switch->getCond())
4689 return;
John McCall5939b162011-08-06 07:30:58 +00004690 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4691 if (!type->isEnumeralType()) {
4692 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004693 Data.IntegralConstantExpression = true;
4694 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004695 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004696 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004697
Douglas Gregord328d572009-09-21 18:10:23 +00004698 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004699 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004700 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004701 if (EnumDecl *Def = Enum->getDefinition())
4702 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004703
Douglas Gregord328d572009-09-21 18:10:23 +00004704 // Determine which enumerators we have already seen in the switch statement.
4705 // FIXME: Ideally, we would also be able to look *past* the code-completion
4706 // token, in case we are code-completing in the middle of the switch and not
4707 // at the end. However, we aren't able to do so at the moment.
4708 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004709 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004710 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004711 SC = SC->getNextSwitchCase()) {
4712 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4713 if (!Case)
4714 continue;
4715
4716 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004717 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4718 if (auto *Enumerator =
4719 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004720 // We look into the AST of the case statement to determine which
4721 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004722 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004723 // values of each enumerator. However, value-based approach would not
4724 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004725 // template are type- and value-dependent.
4726 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004727
Douglas Gregorf2510672009-09-21 19:57:38 +00004728 // If this is a qualified-id, keep track of the nested-name-specifier
4729 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004730 //
4731 // switch (TagD.getKind()) {
4732 // case TagDecl::TK_enum:
4733 // break;
4734 // case XXX
4735 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004736 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004737 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4738 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004739 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004740 }
4741 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004742
David Blaikiebbafb8a2012-03-11 07:00:24 +00004743 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004744 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004745 // qualify the names of the enumerators that we suggest, because they
4746 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004747 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004748 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004749
Douglas Gregord328d572009-09-21 18:10:23 +00004750 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004751 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004752 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004753 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004754 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004755 for (auto *E : Enum->enumerators()) {
4756 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004757 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004758
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004759 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004760 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004761 }
4762 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004763
Douglas Gregor21325842011-07-07 16:03:39 +00004764 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004765 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004766 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004767 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4768 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004769}
4770
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004771static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004772 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004773 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004774
4775 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004776 if (!Args[I])
4777 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004778
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004779 return false;
4780}
4781
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004782typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4783
Fangrui Song050229d2018-11-24 00:14:31 +00004784static void mergeCandidatesWithResults(
4785 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
4786 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004787 if (!CandidateSet.empty()) {
4788 // Sort the overload candidate set by placing the best overloads first.
4789 std::stable_sort(
4790 CandidateSet.begin(), CandidateSet.end(),
4791 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004792 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4793 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004794 });
4795
4796 // Add the remaining viable overload candidates as code-completion results.
Fangrui Song050229d2018-11-24 00:14:31 +00004797 for (OverloadCandidate &Candidate : CandidateSet) {
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004798 if (Candidate.Function && Candidate.Function->isDeleted())
4799 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004800 if (Candidate.Viable)
4801 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004802 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004803 }
4804}
4805
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004806/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004807/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004808static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00004809 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004810
4811 // Given the overloads 'Candidates' for a function call matching all arguments
4812 // up to N, return the type of the Nth parameter if it is the same for all
4813 // overload candidates.
4814 QualType ParamType;
4815 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00004816 if (const auto *FType = Candidate.getFunctionType())
4817 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004818 if (N < Proto->getNumParams()) {
4819 if (ParamType.isNull())
4820 ParamType = Proto->getParamType(N);
4821 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00004822 ParamType.getNonReferenceType(),
4823 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004824 // Otherwise return a default-constructed QualType.
4825 return QualType();
4826 }
4827 }
4828
4829 return ParamType;
4830}
4831
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004832static QualType
4833ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4834 MutableArrayRef<ResultCandidate> Candidates,
4835 unsigned CurrentArg, SourceLocation OpenParLoc) {
4836 if (Candidates.empty())
4837 return QualType();
4838 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4839 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4840 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004841}
4842
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004843QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4844 ArrayRef<Expr *> Args,
4845 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004846 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004847 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004848
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004849 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004850 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004851 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4852 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004853 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004854 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004855
John McCall57500772009-12-16 12:17:52 +00004856 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004857 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004858 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004859
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004860 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004861
John McCall57500772009-12-16 12:17:52 +00004862 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004863 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004864 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004865 /*PartialOverloading=*/true);
4866 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4867 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4868 if (UME->hasExplicitTemplateArgs()) {
4869 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4870 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004871 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004872
4873 // Add the base as first argument (use a nullptr if the base is implicit).
4874 SmallVector<Expr *, 12> ArgExprs(
4875 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004876 ArgExprs.append(Args.begin(), Args.end());
4877 UnresolvedSet<8> Decls;
4878 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004879 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004880 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4881 /*SuppressUsedConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00004882 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004883 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004884 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004885 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004886 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00004887 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004888 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004889 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004890 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004891 !FD->getType()->getAs<FunctionProtoType>())
4892 Results.push_back(ResultCandidate(FD));
4893 else
4894 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4895 Args, CandidateSet,
4896 /*SuppressUsedConversions=*/false,
4897 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004898
4899 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4900 // If expression's type is CXXRecordDecl, it may overload the function
4901 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004902 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004903 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00004904 DeclarationName OpName =
4905 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004906 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4907 LookupQualifiedName(R, DC);
4908 R.suppressDiagnostics();
4909 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4910 ArgExprs.append(Args.begin(), Args.end());
4911 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4912 /*ExplicitArgs=*/nullptr,
4913 /*SuppressUsedConversions=*/false,
4914 /*PartialOverloading=*/true);
4915 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004916 } else {
4917 // Lastly we check whether expression's type is function pointer or
4918 // function.
4919 QualType T = NakedFn->getType();
4920 if (!T->getPointeeType().isNull())
4921 T = T->getPointeeType();
4922
4923 if (auto FP = T->getAs<FunctionProtoType>()) {
4924 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00004925 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004926 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004927 Results.push_back(ResultCandidate(FP));
4928 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004929 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004930 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004931 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004932 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004933 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004934 QualType ParamType =
4935 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4936 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004937}
4938
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004939QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4940 SourceLocation Loc,
4941 ArrayRef<Expr *> Args,
4942 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004943 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004944 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004945
4946 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004947 CXXRecordDecl *RD =
4948 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004949 if (!RD)
4950 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004951
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004952 // FIXME: Provide support for member initializers.
4953 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004954
4955 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4956
Fangrui Song050229d2018-11-24 00:14:31 +00004957 for (NamedDecl *C : LookupConstructors(RD)) {
4958 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
4959 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
4960 CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004961 /*SuppressUsedConversions=*/false,
4962 /*PartialOverloading=*/true);
Fangrui Song050229d2018-11-24 00:14:31 +00004963 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4964 AddTemplateOverloadCandidate(
4965 FTD, DeclAccessPair::make(FTD, C->getAccess()),
4966 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
4967 /*SuppressUsedConversions=*/false,
4968 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004969 }
4970 }
4971
4972 SmallVector<ResultCandidate, 8> Results;
4973 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004974 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004975}
4976
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004977QualType Sema::ProduceCtorInitMemberSignatureHelp(
4978 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4979 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4980 if (!CodeCompleter)
4981 return QualType();
4982
4983 CXXConstructorDecl *Constructor =
4984 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4985 if (!Constructor)
4986 return QualType();
4987 // FIXME: Add support for Base class constructors as well.
4988 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4989 Constructor->getParent(), SS, TemplateTypeTy, II))
4990 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4991 MemberDecl->getLocation(), ArgExprs,
4992 OpenParLoc);
4993 return QualType();
4994}
4995
John McCall48871652010-08-21 09:40:31 +00004996void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4997 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004998 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004999 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005000 return;
5001 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005002
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005003 CodeCompleteExpressionData Data;
5004 Data.PreferredType = VD->getType();
5005 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5006 Data.IgnoreDecls.push_back(VD);
5007
5008 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005009}
5010
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005011void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005012 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005013 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005014 mapCodeCompletionContext(*this, PCC_Statement));
5015 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5016 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005017
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005018 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5019 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005020 CodeCompleter->includeGlobals(),
5021 CodeCompleter->loadExternal());
5022
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005023 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005024
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005025 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005026 CodeCompletionBuilder Builder(Results.getAllocator(),
5027 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005028 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005029 if (Results.includeCodePatterns()) {
5030 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5031 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5032 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5033 Builder.AddPlaceholderChunk("statements");
5034 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5035 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5036 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005037 Results.AddResult(Builder.TakeString());
5038
5039 // "else if" block
5040 Builder.AddTypedTextChunk("else");
5041 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5042 Builder.AddTextChunk("if");
5043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5044 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005045 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005046 Builder.AddPlaceholderChunk("condition");
5047 else
5048 Builder.AddPlaceholderChunk("expression");
5049 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005050 if (Results.includeCodePatterns()) {
5051 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5052 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5053 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5054 Builder.AddPlaceholderChunk("statements");
5055 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5056 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5057 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005058 Results.AddResult(Builder.TakeString());
5059
5060 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005061
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005062 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005063 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005064
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005065 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005066 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005067
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005068 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005069 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005070}
5071
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005072void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005073 bool EnteringContext, QualType BaseType) {
Eric Liu06d34022017-12-12 11:35:46 +00005074 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005075 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005076
Eric Liu06d34022017-12-12 11:35:46 +00005077 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5078 // "a::b::" is not corresponding to any context/namespace in the AST), since
5079 // it can be useful for global code completion which have information about
5080 // contexts/symbols that are not in the AST.
5081 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005082 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00005083 CC.setCXXScopeSpecifier(SS);
Eric Liu206740e2019-02-21 11:22:58 +00005084 // As SS is invalid, we try to collect accessible contexts from the current
5085 // scope with a dummy lookup so that the completion consumer can try to
5086 // guess what the specified scope is.
5087 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5088 CodeCompleter->getCodeCompletionTUInfo(), CC);
5089 if (S->getEntity()) {
5090 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5091 BaseType);
5092 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5093 /*IncludeGlobalScope=*/false,
5094 /*LoadExternal=*/false);
5095 }
5096 HandleCodeCompleteResults(this, CodeCompleter,
5097 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005098 return;
5099 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005100 // Always pretend to enter a context to ensure that a dependent type
5101 // resolves to a dependent record.
5102 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005103 if (!Ctx)
5104 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005105
5106 // Try to instantiate any non-dependent declaration contexts before
5107 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005108 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005109 return;
5110
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005111 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005112 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005113 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005114 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005115
Douglas Gregor3545ff42009-09-21 16:56:56 +00005116 // The "template" keyword can follow "::" in the grammar, but only
5117 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005118 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005119 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005120 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005121
5122 // Add calls to overridden virtual functions, if there are any.
5123 //
5124 // FIXME: This isn't wonderful, because we don't know whether we're actually
5125 // in a context that permits expressions. This is a general issue with
5126 // qualified-id completions.
5127 if (!EnteringContext)
5128 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005129 Results.ExitScope();
5130
Eric Liufead6ae2017-12-13 10:26:49 +00005131 if (CodeCompleter->includeNamespaceLevelDecls() ||
5132 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005133 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005134 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5135 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005136 /*IncludeDependentBases=*/true,
5137 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005138 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005139
Eric Liu06d34022017-12-12 11:35:46 +00005140 auto CC = Results.getCompletionContext();
5141 CC.setCXXScopeSpecifier(SS);
5142
5143 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
5144 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005145}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005146
5147void Sema::CodeCompleteUsing(Scope *S) {
5148 if (!CodeCompleter)
5149 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005150
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005151 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005152 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005153 // This can be both a using alias or using
5154 // declaration, in the former we expect a new name and a
5155 // symbol in the latter case.
5156 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005157 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005158 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005159
Douglas Gregor3545ff42009-09-21 16:56:56 +00005160 // If we aren't in class scope, we could see the "namespace" keyword.
5161 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005162 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005163
5164 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005165 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005166 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005167 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005168 CodeCompleter->includeGlobals(),
5169 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005170 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005171
5172 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5173 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005174}
5175
5176void Sema::CodeCompleteUsingDirective(Scope *S) {
5177 if (!CodeCompleter)
5178 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005179
Douglas Gregor3545ff42009-09-21 16:56:56 +00005180 // After "using namespace", we expect to see a namespace name or namespace
5181 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005182 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005183 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005184 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005185 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005186 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005187 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005188 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005189 CodeCompleter->includeGlobals(),
5190 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005191 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005192 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5193 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005194}
5195
Fangrui Song050229d2018-11-24 00:14:31 +00005196void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005197 if (!CodeCompleter)
5198 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005199
Ted Kremenekc37877d2013-10-08 17:08:03 +00005200 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005201 if (!S->getParent())
5202 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005203
Fangrui Song050229d2018-11-24 00:14:31 +00005204 bool SuppressedGlobalResults =
5205 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005206
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005207 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005208 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005209 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005210 ? CodeCompletionContext::CCC_Namespace
5211 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005212 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005213
Douglas Gregor0ac41382010-09-23 23:01:17 +00005214 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005215 // We only want to see those namespaces that have already been defined
5216 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005217 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005218 // definition of each namespace.
5219 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005220 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005221 NS(Ctx->decls_begin()),
5222 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005223 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005224 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005225
5226 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005227 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005228 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005229 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005230 NS = OrigToLatest.begin(),
5231 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005232 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005233 Results.AddResult(
5234 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5235 nullptr),
5236 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005237 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005238 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005239
Fangrui Song050229d2018-11-24 00:14:31 +00005240 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5241 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005242}
5243
Fangrui Song050229d2018-11-24 00:14:31 +00005244void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005245 if (!CodeCompleter)
5246 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005247
Douglas Gregor3545ff42009-09-21 16:56:56 +00005248 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005249 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005250 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005251 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005252 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005253 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005254 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005255 CodeCompleter->includeGlobals(),
5256 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005257 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5258 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005259}
5260
Douglas Gregorc811ede2009-09-18 20:05:18 +00005261void Sema::CodeCompleteOperatorName(Scope *S) {
5262 if (!CodeCompleter)
5263 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005264
John McCall276321a2010-08-25 06:19:51 +00005265 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005266 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005267 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005268 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005269 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005270 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005271
Douglas Gregor3545ff42009-09-21 16:56:56 +00005272 // Add the names of overloadable operators.
Fangrui Song050229d2018-11-24 00:14:31 +00005273#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5274 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005275 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005276#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005277
Douglas Gregor3545ff42009-09-21 16:56:56 +00005278 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005279 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005280 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005281 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005282 CodeCompleter->includeGlobals(),
5283 CodeCompleter->loadExternal());
5284
Douglas Gregor3545ff42009-09-21 16:56:56 +00005285 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005286 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005287 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005288
5289 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5290 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005291}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005292
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005293void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005294 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005295 if (!ConstructorD)
5296 return;
5297
5298 AdjustDeclIfTemplate(ConstructorD);
5299
Fangrui Song050229d2018-11-24 00:14:31 +00005300 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005301 if (!Constructor)
5302 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005303
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005304 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005305 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005306 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005307 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005308
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005309 // Fill in any already-initialized fields or base classes.
5310 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5311 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005312 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005313 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005314 InitializedBases.insert(Context.getCanonicalType(
5315 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005316 else
Fangrui Song050229d2018-11-24 00:14:31 +00005317 InitializedFields.insert(
5318 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005319 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005320
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005321 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005322 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005323 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005324 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005325
5326 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5327 CodeCompletionBuilder Builder(Results.getAllocator(),
5328 Results.getCodeCompletionTUInfo());
5329 Builder.AddTypedTextChunk(Name);
5330 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005331 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005332 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005333 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005334 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5335 Builder);
5336 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5337 return Builder.TakeString();
5338 };
5339 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5340 const NamedDecl *ND) {
5341 CodeCompletionBuilder Builder(Results.getAllocator(),
5342 Results.getCodeCompletionTUInfo());
5343 Builder.AddTypedTextChunk(Name);
5344 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5345 Builder.AddPlaceholderChunk(Type);
5346 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5347 if (ND) {
5348 auto CCR = CodeCompletionResult(
5349 Builder.TakeString(), ND,
5350 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5351 if (isa<FieldDecl>(ND))
5352 CCR.CursorKind = CXCursor_MemberRef;
5353 return Results.AddResult(CCR);
5354 }
5355 return Results.AddResult(CodeCompletionResult(
5356 Builder.TakeString(),
5357 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5358 };
5359 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5360 const char *Name, const FieldDecl *FD) {
5361 if (!RD)
5362 return AddDefaultCtorInit(Name,
5363 FD ? Results.getAllocator().CopyString(
5364 FD->getType().getAsString(Policy))
5365 : Name,
5366 FD);
5367 auto Ctors = getConstructors(Context, RD);
5368 if (Ctors.begin() == Ctors.end())
5369 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005370 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005371 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5372 CCR.CursorKind = getCursorKindForDecl(Ctor);
5373 Results.AddResult(CCR);
5374 }
5375 };
5376 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5377 const char *BaseName =
5378 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5379 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5380 AddCtorsWithName(
5381 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5382 BaseName, nullptr);
5383 };
5384 auto AddField = [&](const FieldDecl *FD) {
5385 const char *FieldName =
5386 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5387 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5388 AddCtorsWithName(
5389 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5390 FieldName, FD);
5391 };
5392
Aaron Ballman574705e2014-03-13 15:41:46 +00005393 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005394 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5395 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005396 SawLastInitializer =
5397 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5398 Context.hasSameUnqualifiedType(
5399 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005400 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005401 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005402
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005403 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005404 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005405 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005406
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005407 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005408 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005409 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5410 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005411 SawLastInitializer =
5412 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5413 Context.hasSameUnqualifiedType(
5414 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005415 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005416 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005417
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005418 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005419 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005421
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005422 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005423 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005424 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5425 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005426 SawLastInitializer = !Initializers.empty() &&
5427 Initializers.back()->isAnyMemberInitializer() &&
5428 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005429 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005430 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005431
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005432 if (!Field->getDeclName())
5433 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005434
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005435 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005436 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005437 }
5438 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005439
Douglas Gregor0ac41382010-09-23 23:01:17 +00005440 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005441 Results.data(), Results.size());
5442}
5443
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005444/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005445static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005446 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005447 if (!DC)
5448 return false;
5449
5450 return DC->isFileContext();
5451}
5452
5453void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5454 bool AfterAmpersand) {
5455 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005456 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005457 CodeCompletionContext::CCC_Other);
5458 Results.EnterNewScope();
5459
5460 // Note what has already been captured.
5461 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5462 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005463 for (const auto &C : Intro.Captures) {
5464 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005465 IncludedThis = true;
5466 continue;
5467 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005468
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005469 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005470 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005471
Douglas Gregord8c61782012-02-15 15:34:24 +00005472 // Look for other capturable variables.
5473 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005474 for (const auto *D : S->decls()) {
5475 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005476 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005477 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005478
David Blaikie82e95a32014-11-19 07:49:47 +00005479 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005480 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005481 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005482 }
5483 }
5484
5485 // Add 'this', if it would be valid.
5486 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5487 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005488
Douglas Gregord8c61782012-02-15 15:34:24 +00005489 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005490
Douglas Gregord8c61782012-02-15 15:34:24 +00005491 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5492 Results.data(), Results.size());
5493}
5494
James Dennett596e4752012-06-14 03:11:41 +00005495/// Macro that optionally prepends an "@" to the string literal passed in via
5496/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005497#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005498
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005499static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005500 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005501 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005502 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005503 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005504
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005505 CodeCompletionBuilder Builder(Results.getAllocator(),
5506 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005507 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005508 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005509 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005510 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5511 Builder.AddPlaceholderChunk("property");
5512 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005513
Douglas Gregorf1934162010-01-13 21:24:21 +00005514 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005515 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005516 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5517 Builder.AddPlaceholderChunk("property");
5518 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005519 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005520}
5521
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005522static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005523 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005524 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005525
Douglas Gregorf1934162010-01-13 21:24:21 +00005526 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005527 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005528
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005529 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005530 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005531 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005532
Douglas Gregorf1934162010-01-13 21:24:21 +00005533 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005534 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005535
Douglas Gregorf1934162010-01-13 21:24:21 +00005536 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005537 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005538 }
5539}
5540
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005541static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005542 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005543 CodeCompletionBuilder Builder(Results.getAllocator(),
5544 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005545
Douglas Gregorf1934162010-01-13 21:24:21 +00005546 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005547 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005548 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5549 Builder.AddPlaceholderChunk("name");
5550 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005551
Douglas Gregorf4c33342010-05-28 00:22:41 +00005552 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005553 // @interface name
5554 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005555 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005556 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005557 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5558 Builder.AddPlaceholderChunk("class");
5559 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005560
Douglas Gregorf4c33342010-05-28 00:22:41 +00005561 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005562 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005563 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5564 Builder.AddPlaceholderChunk("protocol");
5565 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005566
Douglas Gregorf4c33342010-05-28 00:22:41 +00005567 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005568 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005569 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5570 Builder.AddPlaceholderChunk("class");
5571 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005572 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005573
Douglas Gregorf1934162010-01-13 21:24:21 +00005574 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005575 Builder.AddTypedTextChunk(
5576 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005577 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5578 Builder.AddPlaceholderChunk("alias");
5579 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5580 Builder.AddPlaceholderChunk("class");
5581 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005582
5583 if (Results.getSema().getLangOpts().Modules) {
5584 // @import name
5585 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5586 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5587 Builder.AddPlaceholderChunk("module");
5588 Results.AddResult(Result(Builder.TakeString()));
5589 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005590}
5591
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005592void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005593 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005594 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005595 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005596 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005597 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005598 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005599 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005600 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005601 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005602 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005603 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005604 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5605 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005606}
5607
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005608static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005609 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005610 CodeCompletionBuilder Builder(Results.getAllocator(),
5611 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005612
5613 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005614 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005615 if (Results.getSema().getLangOpts().CPlusPlus ||
5616 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005617 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005618 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005619 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005620 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5621 Builder.AddPlaceholderChunk("type-name");
5622 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5623 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005624
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005625 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005626 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005627 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005628 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5629 Builder.AddPlaceholderChunk("protocol-name");
5630 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5631 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005632
5633 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005634 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005635 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005636 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5637 Builder.AddPlaceholderChunk("selector");
5638 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5639 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005640
5641 // @"string"
5642 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005643 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005644 Builder.AddPlaceholderChunk("string");
5645 Builder.AddTextChunk("\"");
5646 Results.AddResult(Result(Builder.TakeString()));
5647
Douglas Gregor951de302012-07-17 23:24:47 +00005648 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005649 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005650 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005651 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005652 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5653 Results.AddResult(Result(Builder.TakeString()));
5654
Douglas Gregor951de302012-07-17 23:24:47 +00005655 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005656 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005657 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005658 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005659 Builder.AddChunk(CodeCompletionString::CK_Colon);
5660 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5661 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005662 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5663 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005664
Douglas Gregor951de302012-07-17 23:24:47 +00005665 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005666 Builder.AddResultTypeChunk("id");
5667 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005668 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005669 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5670 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005671}
5672
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005673static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005674 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005675 CodeCompletionBuilder Builder(Results.getAllocator(),
5676 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005677
Douglas Gregorf4c33342010-05-28 00:22:41 +00005678 if (Results.includeCodePatterns()) {
5679 // @try { statements } @catch ( declaration ) { statements } @finally
5680 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005681 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005682 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5683 Builder.AddPlaceholderChunk("statements");
5684 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5685 Builder.AddTextChunk("@catch");
5686 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5687 Builder.AddPlaceholderChunk("parameter");
5688 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5689 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5690 Builder.AddPlaceholderChunk("statements");
5691 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5692 Builder.AddTextChunk("@finally");
5693 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5694 Builder.AddPlaceholderChunk("statements");
5695 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5696 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005697 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005698
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005699 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005700 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005701 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5702 Builder.AddPlaceholderChunk("expression");
5703 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005704
Douglas Gregorf4c33342010-05-28 00:22:41 +00005705 if (Results.includeCodePatterns()) {
5706 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005707 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005708 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5709 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5710 Builder.AddPlaceholderChunk("expression");
5711 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5712 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5713 Builder.AddPlaceholderChunk("statements");
5714 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5715 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005716 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005717}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005718
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005719static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005720 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005721 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005722 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5723 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5724 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005725 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005726 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005727}
5728
5729void Sema::CodeCompleteObjCAtVisibility(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 Gregor48d46252010-01-13 21:54:15 +00005733 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005734 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005735 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005736 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5737 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005738}
5739
5740void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005741 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005742 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005743 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005744 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005745 AddObjCStatementResults(Results, false);
5746 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005747 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005748 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5749 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005750}
5751
5752void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005753 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005754 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005755 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005756 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005757 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005758 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005759 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5760 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005761}
5762
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005763/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005764/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005765static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005766 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005767 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005768 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005769
Bill Wendling44426052012-12-20 19:22:21 +00005770 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005771
Douglas Gregore6078da2009-11-19 00:14:45 +00005772 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005773 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5774 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005775 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005776
Jordan Rose53cb2f32012-08-20 20:01:13 +00005777 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00005778 unsigned AssignCopyRetMask =
5779 Attributes &
5780 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
5781 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
5782 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
5783 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005784 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005785 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005786 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005787 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5788 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005789 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005790
Douglas Gregore6078da2009-11-19 00:14:45 +00005791 return false;
5792}
5793
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005794void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005795 if (!CodeCompleter)
5796 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005797
Bill Wendling44426052012-12-20 19:22:21 +00005798 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005799
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005800 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005801 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005802 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005803 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005804 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005805 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005806 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005807 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005808 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005809 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5810 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005811 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005812 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005813 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005814 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005815 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005816 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005817 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005818 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005819 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005820 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005821 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005822 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005823
5824 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005825 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005826 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005827 Results.AddResult(CodeCompletionResult("weak"));
5828
Bill Wendling44426052012-12-20 19:22:21 +00005829 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005830 CodeCompletionBuilder Setter(Results.getAllocator(),
5831 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005832 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005833 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005834 Setter.AddPlaceholderChunk("method");
5835 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005836 }
Bill Wendling44426052012-12-20 19:22:21 +00005837 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005838 CodeCompletionBuilder Getter(Results.getAllocator(),
5839 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005840 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005841 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005842 Getter.AddPlaceholderChunk("method");
5843 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005844 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005845 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5846 Results.AddResult(CodeCompletionResult("nonnull"));
5847 Results.AddResult(CodeCompletionResult("nullable"));
5848 Results.AddResult(CodeCompletionResult("null_unspecified"));
5849 Results.AddResult(CodeCompletionResult("null_resettable"));
5850 }
Steve Naroff936354c2009-10-08 21:55:05 +00005851 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005852 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5853 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005854}
Steve Naroffeae65032009-11-07 02:08:14 +00005855
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005856/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005857/// via code completion.
5858enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005859 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5860 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00005861 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005862};
5863
Fangrui Song050229d2018-11-24 00:14:31 +00005864static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005865 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005866 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005867 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005868 if (NumSelIdents > Sel.getNumArgs())
5869 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005870
Douglas Gregor67c692c2010-08-26 15:07:07 +00005871 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00005872 case MK_Any:
5873 break;
5874 case MK_ZeroArgSelector:
5875 return Sel.isUnarySelector();
5876 case MK_OneArgSelector:
5877 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005878 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005879
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005880 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5881 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005882
Douglas Gregor67c692c2010-08-26 15:07:07 +00005883 for (unsigned I = 0; I != NumSelIdents; ++I)
5884 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5885 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005886
Douglas Gregor67c692c2010-08-26 15:07:07 +00005887 return true;
5888}
5889
Douglas Gregorc8537c52009-11-19 07:41:15 +00005890static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5891 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005892 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005893 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005894 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005895 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005896}
Douglas Gregor1154e272010-09-16 16:06:31 +00005897
Fangrui Song050229d2018-11-24 00:14:31 +00005898/// A set of selectors, which is used to avoid introducing multiple
5899/// completions with the same selector into the result set.
5900typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00005901
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005902/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005903/// container to the set of results.
5904///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005905/// The container will be a class, protocol, category, or implementation of
5906/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005907/// the superclasses of classes along with their categories, protocols, and
5908/// implementations.
5909///
5910/// \param Container the container in which we'll look to find methods.
5911///
James Dennett596e4752012-06-14 03:11:41 +00005912/// \param WantInstanceMethods Whether to add instance methods (only); if
5913/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005914///
5915/// \param CurContext the context in which we're performing the lookup that
5916/// finds methods.
5917///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005918/// \param AllowSameLength Whether we allow a method to be added to the list
5919/// when it has the same number of parameters as we have selector identifiers.
5920///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005921/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005922static void AddObjCMethods(ObjCContainerDecl *Container,
5923 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005924 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005925 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005926 VisitedSelectorSet &Selectors, bool AllowSameLength,
5927 ResultBuilder &Results, bool InOriginalClass = true,
5928 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005929 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005930 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005931 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005932 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00005933 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005934 // The instance methods on the root class can be messaged via the
5935 // metaclass.
5936 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005937 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005938 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005939 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005940 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005941 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005942
David Blaikie82e95a32014-11-19 07:49:47 +00005943 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005944 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005945
5946 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005947 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005948 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005949 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00005950 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00005951 Results.MaybeAddResult(R, CurContext);
5952 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005953 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005954
Douglas Gregorf37c9492010-09-16 15:34:59 +00005955 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005956 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005957 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00005958 const ObjCList<ObjCProtocolDecl> &Protocols =
5959 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005960 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005961 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005962 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005963 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5964 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005965 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005966 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005967
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005968 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005969 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005970
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005971 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005972 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005973 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5974 Selectors, AllowSameLength, Results, false, IsRootClass);
5975
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005976 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00005977 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005978 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005979 CurContext, Selectors, AllowSameLength, Results,
5980 InOriginalClass, IsRootClass);
5981
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005982 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00005983 const ObjCList<ObjCProtocolDecl> &Protocols =
5984 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005985 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5986 E = Protocols.end();
5987 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005988 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5989 Selectors, AllowSameLength, Results, false, IsRootClass);
5990
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005991 // Add methods in category implementations.
5992 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005993 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5994 Selectors, AllowSameLength, Results, InOriginalClass,
5995 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005996 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005997
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005998 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005999 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006000 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006001 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6002 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6003 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006004
6005 // Add methods in our implementation, if any.
6006 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006007 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6008 Selectors, AllowSameLength, Results, InOriginalClass,
6009 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006010}
6011
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006012void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006013 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006014 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006015 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006016 if (ObjCCategoryDecl *Category =
6017 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006018 Class = Category->getClassInterface();
6019
6020 if (!Class)
6021 return;
6022 }
6023
6024 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006025 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006026 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006027 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006028 Results.EnterNewScope();
6029
Douglas Gregor1154e272010-09-16 16:06:31 +00006030 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006031 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006032 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006033 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006034 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6035 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006036}
6037
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006038void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006039 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006040 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006041 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006042 if (ObjCCategoryDecl *Category =
6043 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006044 Class = Category->getClassInterface();
6045
6046 if (!Class)
6047 return;
6048 }
6049
6050 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006051 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006052 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006053 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006054 Results.EnterNewScope();
6055
Douglas Gregor1154e272010-09-16 16:06:31 +00006056 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006057 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6058 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006059
6060 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006061 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6062 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006063}
6064
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006065void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6066 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006067 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006068 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006069 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006070 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006071
Douglas Gregor99fa2642010-08-24 01:06:58 +00006072 // Add context-sensitive, Objective-C parameter-passing keywords.
6073 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006074 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006075 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6076 Results.AddResult("in");
6077 Results.AddResult("inout");
6078 AddedInOut = true;
6079 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006080 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006081 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6082 Results.AddResult("out");
6083 if (!AddedInOut)
6084 Results.AddResult("inout");
6085 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006086 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006087 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6088 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006089 Results.AddResult("bycopy");
6090 Results.AddResult("byref");
6091 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006092 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006093 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6094 Results.AddResult("nonnull");
6095 Results.AddResult("nullable");
6096 Results.AddResult("null_unspecified");
6097 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006098
6099 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006100 // identifier IBAction refers to a macro, provide a completion item for
6101 // an action, e.g.,
6102 // IBAction)<#selector#>:(id)sender
6103 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006104 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006105 CodeCompletionBuilder Builder(Results.getAllocator(),
6106 Results.getCodeCompletionTUInfo(),
6107 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006108 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006109 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006110 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006111 Builder.AddChunk(CodeCompletionString::CK_Colon);
6112 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006113 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006114 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006115 Builder.AddTextChunk("sender");
6116 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6117 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006118
6119 // If we're completing the return type, provide 'instancetype'.
6120 if (!IsParameter) {
6121 Results.AddResult(CodeCompletionResult("instancetype"));
6122 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006123
Douglas Gregor99fa2642010-08-24 01:06:58 +00006124 // Add various builtin type names and specifiers.
6125 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6126 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006127
Douglas Gregor99fa2642010-08-24 01:06:58 +00006128 // Add the various type names
6129 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6130 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6131 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006132 CodeCompleter->includeGlobals(),
6133 CodeCompleter->loadExternal());
6134
Douglas Gregor99fa2642010-08-24 01:06:58 +00006135 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006136 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006137
Eric Liuf5ba09f2018-07-04 10:01:18 +00006138 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006139 Results.data(), Results.size());
6140}
6141
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006142/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006143/// that it has some more-specific class type based on knowledge of
6144/// common uses of Objective-C. This routine returns that class type,
6145/// or NULL if no better result could be determined.
6146static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006147 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006148 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006149 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006150
6151 Selector Sel = Msg->getSelector();
6152 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006153 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006154
6155 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6156 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006157 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006158
6159 ObjCMethodDecl *Method = Msg->getMethodDecl();
6160 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006161 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006162
6163 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006164 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006165 switch (Msg->getReceiverKind()) {
6166 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006167 if (const ObjCObjectType *ObjType =
6168 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006169 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006170 break;
6171
6172 case ObjCMessageExpr::Instance: {
6173 QualType T = Msg->getInstanceReceiver()->getType();
6174 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6175 IFace = Ptr->getInterfaceDecl();
6176 break;
6177 }
6178
6179 case ObjCMessageExpr::SuperInstance:
6180 case ObjCMessageExpr::SuperClass:
6181 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006182 }
6183
6184 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006185 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006186
6187 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6188 if (Method->isInstanceMethod())
6189 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006190 .Case("retain", IFace)
6191 .Case("strong", IFace)
6192 .Case("autorelease", IFace)
6193 .Case("copy", IFace)
6194 .Case("copyWithZone", IFace)
6195 .Case("mutableCopy", IFace)
6196 .Case("mutableCopyWithZone", IFace)
6197 .Case("awakeFromCoder", IFace)
6198 .Case("replacementObjectFromCoder", IFace)
6199 .Case("class", IFace)
6200 .Case("classForCoder", IFace)
6201 .Case("superclass", Super)
6202 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006203
6204 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006205 .Case("new", IFace)
6206 .Case("alloc", IFace)
6207 .Case("allocWithZone", IFace)
6208 .Case("class", IFace)
6209 .Case("superclass", Super)
6210 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006211}
6212
Douglas Gregor6fc04132010-08-27 15:10:57 +00006213// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006214// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006215// function.
6216///
6217/// \param S The semantic analysis object.
6218///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006219/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006220/// the "super" keyword. Otherwise, we just need to provide the arguments.
6221///
6222/// \param SelIdents The identifiers in the selector that have already been
6223/// provided as arguments for a send to "super".
6224///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006225/// \param Results The set of results to augment.
6226///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006227/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006228/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006229static ObjCMethodDecl *
6230AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6231 ArrayRef<IdentifierInfo *> SelIdents,
6232 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006233 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6234 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006235 return nullptr;
6236
Douglas Gregor6fc04132010-08-27 15:10:57 +00006237 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6238 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006239 return nullptr;
6240
Douglas Gregor6fc04132010-08-27 15:10:57 +00006241 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006242 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006243 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6244 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006245 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006246 CurMethod->isInstanceMethod());
6247
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006248 // Check in categories or class extensions.
6249 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006250 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006251 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006252 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006253 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006254 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006255 }
6256 }
6257
Douglas Gregor6fc04132010-08-27 15:10:57 +00006258 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006259 return nullptr;
6260
Douglas Gregor6fc04132010-08-27 15:10:57 +00006261 // Check whether the superclass method has the same signature.
6262 if (CurMethod->param_size() != SuperMethod->param_size() ||
6263 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006264 return nullptr;
6265
Douglas Gregor6fc04132010-08-27 15:10:57 +00006266 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006267 CurPEnd = CurMethod->param_end(),
6268 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006269 CurP != CurPEnd; ++CurP, ++SuperP) {
6270 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006271 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006272 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006273 return nullptr;
6274
Douglas Gregor6fc04132010-08-27 15:10:57 +00006275 // Make sure we have a parameter name to forward!
6276 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006277 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006278 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006279
Douglas Gregor6fc04132010-08-27 15:10:57 +00006280 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006281 CodeCompletionBuilder Builder(Results.getAllocator(),
6282 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006283
Douglas Gregor6fc04132010-08-27 15:10:57 +00006284 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006285 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006286 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006287
6288 // If we need the "super" keyword, add it (plus some spacing).
6289 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006290 Builder.AddTypedTextChunk("super");
6291 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006292 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006293
Douglas Gregor6fc04132010-08-27 15:10:57 +00006294 Selector Sel = CurMethod->getSelector();
6295 if (Sel.isUnarySelector()) {
6296 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006297 Builder.AddTextChunk(
6298 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006299 else
Fangrui Song050229d2018-11-24 00:14:31 +00006300 Builder.AddTypedTextChunk(
6301 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006302 } else {
6303 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6304 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006305 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006306 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006307
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006308 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006309 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006310 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006311 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006312 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006313 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006314 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006315 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006316 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006317 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006318 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006319 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006320 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006321 }
6322 }
6323 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006324
Douglas Gregor78254c82012-03-27 23:34:16 +00006325 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6326 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006327 return SuperMethod;
6328}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006329
Douglas Gregora817a192010-05-27 23:06:34 +00006330void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006331 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006332 ResultBuilder Results(
6333 *this, CodeCompleter->getAllocator(),
6334 CodeCompleter->getCodeCompletionTUInfo(),
6335 CodeCompletionContext::CCC_ObjCMessageReceiver,
6336 getLangOpts().CPlusPlus11
6337 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6338 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006339
Douglas Gregora817a192010-05-27 23:06:34 +00006340 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6341 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006342 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006343 CodeCompleter->includeGlobals(),
6344 CodeCompleter->loadExternal());
6345
Douglas Gregora817a192010-05-27 23:06:34 +00006346 // If we are in an Objective-C method inside a class that has a superclass,
6347 // add "super" as an option.
6348 if (ObjCMethodDecl *Method = getCurMethodDecl())
6349 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006350 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006351 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006352
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006353 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006354 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006355
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006356 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006357 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006358
Douglas Gregora817a192010-05-27 23:06:34 +00006359 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006360
Douglas Gregora817a192010-05-27 23:06:34 +00006361 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006362 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006363 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006364 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006365}
6366
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006367void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006368 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006369 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006370 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006371 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6372 // Figure out which interface we're in.
6373 CDecl = CurMethod->getClassInterface();
6374 if (!CDecl)
6375 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006376
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006377 // Find the superclass of this class.
6378 CDecl = CDecl->getSuperClass();
6379 if (!CDecl)
6380 return;
6381
6382 if (CurMethod->isInstanceMethod()) {
6383 // We are inside an instance method, which means that the message
6384 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006385 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006386 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006387 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006388 }
6389
6390 // Fall through to send to the superclass in CDecl.
6391 } else {
6392 // "super" may be the name of a type or variable. Figure out which
6393 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006394 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006395 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006396 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6397 // "super" names an interface. Use it.
6398 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006399 if (const ObjCObjectType *Iface =
6400 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006401 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006402 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6403 // "super" names an unresolved type; we can't be more specific.
6404 } else {
6405 // Assume that "super" names some kind of value and parse that way.
6406 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006407 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006408 UnqualifiedId id;
6409 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006410 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6411 /*HasTrailingLParen=*/false,
6412 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006413 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006414 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006415 }
6416
6417 // Fall through
6418 }
6419
John McCallba7bf592010-08-24 05:47:05 +00006420 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006421 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006422 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006423 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006424 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006425 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006426}
6427
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006428/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006429/// send, determine the preferred type (if any) for that argument expression.
6430static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6431 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006432 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006433 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006434
Douglas Gregor74661272010-09-21 00:03:25 +00006435 QualType PreferredType;
6436 unsigned BestPriority = CCP_Unlikely * 2;
6437 Result *ResultsData = Results.data();
6438 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6439 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006440 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006441 isa<ObjCMethodDecl>(R.Declaration)) {
6442 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006443 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006444 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006445 QualType MyPreferredType =
6446 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006447 if (R.Priority < BestPriority || PreferredType.isNull()) {
6448 BestPriority = R.Priority;
6449 PreferredType = MyPreferredType;
6450 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6451 MyPreferredType)) {
6452 PreferredType = QualType();
6453 }
6454 }
6455 }
6456 }
6457 }
6458
6459 return PreferredType;
6460}
6461
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006462static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006463 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006464 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006465 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006466 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006467 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006468 ObjCInterfaceDecl *CDecl = nullptr;
6469
Douglas Gregor8ce33212009-11-17 17:59:40 +00006470 // If the given name refers to an interface type, retrieve the
6471 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006472 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006473 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006474 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006475 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6476 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006477 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006478
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006479 // Add all of the factory methods in this Objective-C class, its protocols,
6480 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006481 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006482
6483 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006484 // completion.
6485 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006486 if (ObjCMethodDecl *SuperMethod =
6487 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006488 Results.Ignore(SuperMethod);
6489 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006490
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006491 // If we're inside an Objective-C method definition, prefer its selector to
6492 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006493 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006494 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006495
Douglas Gregor1154e272010-09-16 16:06:31 +00006496 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006497 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006498 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6499 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006500 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006501 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006502
Douglas Gregord720daf2010-04-06 17:30:22 +00006503 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006504 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006505 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006506 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006507 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006508 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006509 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006510 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006511 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006512
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006513 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006514 }
6515 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006516
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006517 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006518 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006519 M != MEnd; ++M) {
6520 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006521 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006522 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006523 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006524
Nico Weber2e0c8f72014-12-27 03:58:08 +00006525 Result R(MethList->getMethod(),
6526 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006527 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006528 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006529 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006530 }
6531 }
6532 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006533
6534 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006535}
Douglas Gregor6285f752010-04-06 16:40:00 +00006536
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006537void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006538 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006539 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006540 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006541
Douglas Gregor63745d52011-07-21 01:05:26 +00006542 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006543
Fangrui Song050229d2018-11-24 00:14:31 +00006544 ResultBuilder Results(
6545 *this, CodeCompleter->getAllocator(),
6546 CodeCompleter->getCodeCompletionTUInfo(),
6547 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6548 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006549
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006550 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006551 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006552
6553 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006554 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006555 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006556 // code-complete the expression using the corresponding parameter type as
6557 // our preferred type, improving completion results.
6558 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006559 QualType PreferredType =
6560 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006561 if (PreferredType.isNull())
6562 CodeCompleteOrdinaryName(S, PCC_Expression);
6563 else
6564 CodeCompleteExpression(S, PreferredType);
6565 return;
6566 }
6567
Fangrui Song050229d2018-11-24 00:14:31 +00006568 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006569 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006570}
6571
Richard Trieu2bd04012011-09-09 02:00:50 +00006572void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006573 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006574 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006575 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006576 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006577
Steve Naroffeae65032009-11-07 02:08:14 +00006578 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006579
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006580 // If necessary, apply function/array conversion to the receiver.
6581 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006582 if (RecExpr) {
6583 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6584 if (Conv.isInvalid()) // conversion failed. bail.
6585 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006586 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006587 }
Fangrui Song050229d2018-11-24 00:14:31 +00006588 QualType ReceiverType = RecExpr
6589 ? RecExpr->getType()
6590 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006591 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006592 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006593
Douglas Gregordc520b02010-11-08 21:12:30 +00006594 // If we're messaging an expression with type "id" or "Class", check
6595 // whether we know something special about the receiver that allows
6596 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006597 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006598 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6599 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006600 return CodeCompleteObjCClassMessage(
6601 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6602 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006603
Fangrui Song050229d2018-11-24 00:14:31 +00006604 ReceiverType =
6605 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006606 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006607 } else if (RecExpr && getLangOpts().CPlusPlus) {
6608 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6609 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006610 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006611 ReceiverType = RecExpr->getType();
6612 }
6613 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006614
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006615 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006616 ResultBuilder Results(
6617 *this, CodeCompleter->getAllocator(),
6618 CodeCompleter->getCodeCompletionTUInfo(),
6619 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6620 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006621
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006622 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006623
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006624 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006625 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006626 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006627 if (ObjCMethodDecl *SuperMethod =
6628 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006629 Results.Ignore(SuperMethod);
6630 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006631
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006632 // If we're inside an Objective-C method definition, prefer its selector to
6633 // others.
6634 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6635 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006636
Douglas Gregor1154e272010-09-16 16:06:31 +00006637 // Keep track of the selectors we've already added.
6638 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006639
Douglas Gregora3329fa2009-11-18 00:06:18 +00006640 // Handle messages to Class. This really isn't a message to an instance
6641 // method, so we treat it the same way we would treat a message send to a
6642 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006643 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006644 ReceiverType->isObjCQualifiedClassType()) {
6645 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6646 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006647 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6648 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006649 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006650 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006651 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006652 else if (const ObjCObjectPointerType *QualID =
6653 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006654 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006655 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006656 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6657 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006658 }
6659 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006660 else if (const ObjCObjectPointerType *IFacePtr =
6661 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006662 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006663 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006664 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006665
Douglas Gregora3329fa2009-11-18 00:06:18 +00006666 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006667 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006668 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6669 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006670 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006671 // Handle messages to "id".
6672 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006673 // We're messaging "id", so provide all instance methods we know
6674 // about as code-completion results.
6675
6676 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006677 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006678 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006679 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6680 I != N; ++I) {
6681 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006682 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006683 continue;
6684
Sebastian Redl75d8a322010-08-02 23:18:59 +00006685 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006686 }
6687 }
6688
Sebastian Redl75d8a322010-08-02 23:18:59 +00006689 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6690 MEnd = MethodPool.end();
6691 M != MEnd; ++M) {
6692 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006693 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006694 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006695 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006696
Nico Weber2e0c8f72014-12-27 03:58:08 +00006697 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006698 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006699
Nico Weber2e0c8f72014-12-27 03:58:08 +00006700 Result R(MethList->getMethod(),
6701 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006702 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006703 R.AllParametersAreInformative = false;
6704 Results.MaybeAddResult(R, CurContext);
6705 }
6706 }
6707 }
Steve Naroffeae65032009-11-07 02:08:14 +00006708 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006709
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006710 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006711 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006712 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006713 // code-complete the expression using the corresponding parameter type as
6714 // our preferred type, improving completion results.
6715 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006716 QualType PreferredType =
6717 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006718 if (PreferredType.isNull())
6719 CodeCompleteOrdinaryName(S, PCC_Expression);
6720 else
6721 CodeCompleteExpression(S, PreferredType);
6722 return;
6723 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006724
Fangrui Song050229d2018-11-24 00:14:31 +00006725 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6726 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006727}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006728
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006729void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006730 DeclGroupPtrTy IterationVar) {
6731 CodeCompleteExpressionData Data;
6732 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006733
Douglas Gregor68762e72010-08-23 21:17:50 +00006734 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006735 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006736 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6737 if (*I)
6738 Data.IgnoreDecls.push_back(*I);
6739 }
6740 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006741
Douglas Gregor68762e72010-08-23 21:17:50 +00006742 CodeCompleteExpression(S, Data);
6743}
6744
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006745void Sema::CodeCompleteObjCSelector(Scope *S,
6746 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006747 // If we have an external source, load the entire class method
6748 // pool from the AST file.
6749 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00006750 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
6751 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006752 Selector Sel = ExternalSource->GetExternalSelector(I);
6753 if (Sel.isNull() || MethodPool.count(Sel))
6754 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006755
Douglas Gregor67c692c2010-08-26 15:07:07 +00006756 ReadMethodPool(Sel);
6757 }
6758 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006759
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006760 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006761 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006762 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006763 Results.EnterNewScope();
6764 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006765 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006766 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006767
Douglas Gregor67c692c2010-08-26 15:07:07 +00006768 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006769 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006770 continue;
6771
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006772 CodeCompletionBuilder Builder(Results.getAllocator(),
6773 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006774 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006775 Builder.AddTypedTextChunk(
6776 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006777 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006778 continue;
6779 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006780
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006781 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006782 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006783 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006784 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006785 Builder.AddInformativeChunk(
6786 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006787 Accumulator.clear();
6788 }
6789 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006790
Benjamin Kramer632500c2011-07-26 16:59:25 +00006791 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006792 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006793 }
Fangrui Song050229d2018-11-24 00:14:31 +00006794 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006795 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006796 }
6797 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006798
6799 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006800 Results.data(), Results.size());
6801}
6802
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006803/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006804/// (translation unit) context.
6805static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006806 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006807 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006808 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006809
Aaron Ballman629afae2014-03-07 19:56:05 +00006810 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006811 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006812 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006813 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00006814 Results.AddResult(
6815 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
6816 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006817 }
6818}
6819
Craig Topper883dd332015-12-24 23:58:11 +00006820void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00006821 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006822 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006823 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006824 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006825
Chandler Carruthede11632016-11-04 06:06:50 +00006826 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006827 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006828
Douglas Gregora3b23b02010-12-09 21:44:02 +00006829 // Tell the result set to ignore all of the protocols we have
6830 // already seen.
6831 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006832 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00006833 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006834 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006835
Douglas Gregora3b23b02010-12-09 21:44:02 +00006836 // Add all protocols.
6837 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6838 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006839
Douglas Gregora3b23b02010-12-09 21:44:02 +00006840 Results.ExitScope();
6841 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006842
6843 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6844 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006845}
6846
6847void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006848 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006849 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006850 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006851
Chandler Carruthede11632016-11-04 06:06:50 +00006852 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006853 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006854
Douglas Gregora3b23b02010-12-09 21:44:02 +00006855 // Add all protocols.
6856 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6857 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006858
Douglas Gregora3b23b02010-12-09 21:44:02 +00006859 Results.ExitScope();
6860 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006861
6862 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6863 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006864}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006865
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006866/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006867/// the given (translation unit) context.
6868static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6869 bool OnlyForwardDeclarations,
6870 bool OnlyUnimplemented,
6871 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006872 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006873
Aaron Ballman629afae2014-03-07 19:56:05 +00006874 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006875 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006876 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006877 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006878 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00006879 Results.AddResult(
6880 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
6881 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006882 }
6883}
6884
Eric Liuf5ba09f2018-07-04 10:01:18 +00006885void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006886 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006887 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006888 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006889 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006890
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006891 if (CodeCompleter->includeGlobals()) {
6892 // Add all classes.
6893 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6894 false, Results);
6895 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006896
Douglas Gregor49c22a72009-11-18 16:26:39 +00006897 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006898
Eric Liuf5ba09f2018-07-04 10:01:18 +00006899 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6900 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006901}
6902
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006903void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006904 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006905 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006906 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006907 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006908 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006909
Douglas Gregor49c22a72009-11-18 16:26:39 +00006910 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00006911 NamedDecl *CurClass =
6912 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006913 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006914 Results.Ignore(CurClass);
6915
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006916 if (CodeCompleter->includeGlobals()) {
6917 // Add all classes.
6918 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6919 false, Results);
6920 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006921
Douglas Gregor49c22a72009-11-18 16:26:39 +00006922 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006923
Eric Liuf5ba09f2018-07-04 10:01:18 +00006924 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6925 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006926}
6927
Eric Liuf5ba09f2018-07-04 10:01:18 +00006928void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006929 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006930 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006931 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006932 Results.EnterNewScope();
6933
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006934 if (CodeCompleter->includeGlobals()) {
6935 // Add all unimplemented classes.
6936 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6937 true, Results);
6938 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006939
Douglas Gregor49c22a72009-11-18 16:26:39 +00006940 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006941
Eric Liuf5ba09f2018-07-04 10:01:18 +00006942 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6943 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006944}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006945
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006946void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006947 IdentifierInfo *ClassName,
6948 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006949 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006950
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006951 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006952 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006953 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006954
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006955 // Ignore any categories we find that have already been implemented by this
6956 // interface.
6957 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00006958 NamedDecl *CurClass =
6959 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
6960 if (ObjCInterfaceDecl *Class =
6961 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006962 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006963 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006964 }
6965
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006966 // Add all of the categories we know about.
6967 Results.EnterNewScope();
6968 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006969 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006970 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006971 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00006972 Results.AddResult(
6973 Result(Category, Results.getBasePriority(Category), nullptr),
6974 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006975 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006976
6977 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6978 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006979}
6980
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006981void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006982 IdentifierInfo *ClassName,
6983 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006984 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006985
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006986 // Find the corresponding interface. If we couldn't find the interface, the
6987 // program itself is ill-formed. However, we'll try to be helpful still by
6988 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00006989 NamedDecl *CurClass =
6990 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006991 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6992 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006993 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006994
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006995 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006996 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006997 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006998
6999 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007000 // declarations in this class and any of its superclasses, except for
7001 // already-implemented categories in the class itself.
7002 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7003 Results.EnterNewScope();
7004 bool IgnoreImplemented = true;
7005 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007006 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007007 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007008 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007009 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7010 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007011 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007012
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007013 Class = Class->getSuperClass();
7014 IgnoreImplemented = false;
7015 }
7016 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007017
7018 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7019 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007020}
Douglas Gregor5d649882009-11-18 22:32:06 +00007021
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007022void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007023 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007024 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007025 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007026
7027 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007028 ObjCContainerDecl *Container =
7029 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7030 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7031 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007032 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007033
7034 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007035 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007036 for (const auto *D : Container->decls())
7037 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007038 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007039
Douglas Gregor5d649882009-11-18 22:32:06 +00007040 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007041 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007042 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007043 if (ObjCImplementationDecl *ClassImpl =
7044 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007045 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007046 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007047 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007048 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007049 AddObjCProperties(CCContext,
7050 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007051 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007052 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007053 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007054
7055 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7056 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007057}
7058
Fangrui Song050229d2018-11-24 00:14:31 +00007059void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7060 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007061 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007062 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007063 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007064 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007065
7066 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007067 ObjCContainerDecl *Container =
7068 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7069 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7070 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007071 return;
7072
Douglas Gregor5d649882009-11-18 22:32:06 +00007073 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007074 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007075 if (ObjCImplementationDecl *ClassImpl =
7076 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007077 Class = ClassImpl->getClassInterface();
7078 else
Fangrui Song050229d2018-11-24 00:14:31 +00007079 Class = cast<ObjCCategoryImplDecl>(Container)
7080 ->getCategoryDecl()
7081 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007082
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007083 // Determine the type of the property we're synthesizing.
7084 QualType PropertyType = Context.getObjCIdType();
7085 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007086 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7087 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007088 PropertyType =
7089 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007090
7091 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007092 Results.setPreferredType(PropertyType);
7093 }
7094 }
7095
Douglas Gregor5d649882009-11-18 22:32:06 +00007096 // Add all of the instance variables in this class and its superclasses.
7097 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007098 bool SawSimilarlyNamedIvar = false;
7099 std::string NameWithPrefix;
7100 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007101 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007102 std::string NameWithSuffix = PropertyName->getName().str();
7103 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007104 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007105 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007106 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007107 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7108 CurContext, nullptr, false);
7109
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007110 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007111 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007112 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007113 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007114 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007115 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007116
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007117 // Reduce the priority of this result by one, to give it a slight
7118 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007119 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007120 Results.data()[Results.size() - 1].Kind ==
7121 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007122 Results.data()[Results.size() - 1].Declaration == Ivar)
7123 Results.data()[Results.size() - 1].Priority--;
7124 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007125 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007126 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007127
Douglas Gregor331faa02011-04-18 14:13:53 +00007128 if (!SawSimilarlyNamedIvar) {
7129 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007130 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007131 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007132 typedef CodeCompletionResult Result;
7133 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007134 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007135 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007136
Douglas Gregor75acd922011-09-27 23:30:47 +00007137 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007138 Builder.AddResultTypeChunk(
7139 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007140 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007141 Results.AddResult(
7142 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007143 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007144
Douglas Gregor5d649882009-11-18 22:32:06 +00007145 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007146
7147 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7148 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007149}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007150
Douglas Gregor416b5752010-08-25 01:08:01 +00007151// Mapping from selectors to the methods that implement that selector, along
7152// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007153typedef llvm::DenseMap<Selector,
7154 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7155 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007156
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007157/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007158/// (and its superclasses, protocols, etc.) that meet the given
7159/// criteria. Insert those methods into the map of known methods,
7160/// indexed by selector so they can be easily found.
7161static void FindImplementableMethods(ASTContext &Context,
7162 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007163 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007164 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007165 KnownMethodsMap &KnownMethods,
7166 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007167 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007168 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007169 if (!IFace->hasDefinition())
7170 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007171
7172 IFace = IFace->getDefinition();
7173 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007174
Fangrui Song050229d2018-11-24 00:14:31 +00007175 const ObjCList<ObjCProtocolDecl> &Protocols =
7176 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007177 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007178 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007179 I != E; ++I)
7180 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007181 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007182
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007183 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007184 for (auto *Cat : IFace->visible_categories()) {
7185 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007186 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007187 }
7188
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007189 // Visit the superclass.
7190 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007191 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007192 WantInstanceMethods, ReturnType, KnownMethods,
7193 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007194 }
7195
7196 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7197 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007198 const ObjCList<ObjCProtocolDecl> &Protocols =
7199 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007200 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007201 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007202 I != E; ++I)
7203 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007204 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007205
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007206 // If this category is the original class, jump to the interface.
7207 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007208 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007209 WantInstanceMethods, ReturnType, KnownMethods,
7210 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007211 }
7212
7213 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007214 // Make sure we have a definition; that's what we'll walk.
7215 if (!Protocol->hasDefinition())
7216 return;
7217 Protocol = Protocol->getDefinition();
7218 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007219
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007220 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007221 const ObjCList<ObjCProtocolDecl> &Protocols =
7222 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007223 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007224 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007225 I != E; ++I)
7226 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7227 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007228 }
7229
7230 // Add methods in this container. This operation occurs last because
7231 // we want the methods from this container to override any methods
7232 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007233 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007234 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007235 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007236 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007237 continue;
7238
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007239 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007240 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007241 }
7242 }
7243}
7244
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007245/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007246/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007247static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007248 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007249 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007250 CodeCompletionBuilder &Builder) {
7251 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007252 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007253 if (!Quals.empty())
7254 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007255 Builder.AddTextChunk(
7256 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007257 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7258}
7259
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007260/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007261/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007262static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007263 if (!Class)
7264 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007265
Douglas Gregor669a25a2011-02-17 00:22:45 +00007266 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7267 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007268
Douglas Gregor669a25a2011-02-17 00:22:45 +00007269 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7270}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007271
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007272/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007273/// Key-Value Observing (KVO).
7274static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7275 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007276 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007277 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007278 ResultBuilder &Results) {
7279 IdentifierInfo *PropName = Property->getIdentifier();
7280 if (!PropName || PropName->getLength() == 0)
7281 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007282
Douglas Gregor75acd922011-09-27 23:30:47 +00007283 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7284
Douglas Gregor669a25a2011-02-17 00:22:45 +00007285 // Builder that will create each code completion.
7286 typedef CodeCompletionResult Result;
7287 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007288 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007289
Douglas Gregor669a25a2011-02-17 00:22:45 +00007290 // The selector table.
7291 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007292
Douglas Gregor669a25a2011-02-17 00:22:45 +00007293 // The property name, copied into the code completion allocation region
7294 // on demand.
7295 struct KeyHolder {
7296 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007297 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007298 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007299
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007300 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007301 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007302
Douglas Gregor669a25a2011-02-17 00:22:45 +00007303 operator const char *() {
7304 if (CopiedKey)
7305 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007306
Douglas Gregor669a25a2011-02-17 00:22:45 +00007307 return CopiedKey = Allocator.CopyString(Key);
7308 }
7309 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007310
Douglas Gregor669a25a2011-02-17 00:22:45 +00007311 // The uppercased name of the property name.
7312 std::string UpperKey = PropName->getName();
7313 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007314 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007315
Fangrui Song050229d2018-11-24 00:14:31 +00007316 bool ReturnTypeMatchesProperty =
7317 ReturnType.isNull() ||
7318 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7319 Property->getType());
7320 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007321
Douglas Gregor669a25a2011-02-17 00:22:45 +00007322 // Add the normal accessor -(type)key.
7323 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007324 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007325 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7326 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007327 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7328 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007329
Douglas Gregor669a25a2011-02-17 00:22:45 +00007330 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007331 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007332 CXCursor_ObjCInstanceMethodDecl));
7333 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007334
Douglas Gregor669a25a2011-02-17 00:22:45 +00007335 // If we have an integral or boolean property (or the user has provided
7336 // an integral or boolean return type), add the accessor -(type)isKey.
7337 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007338 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007339 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007340 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7341 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007342 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007343 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007344 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7345 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007346 if (ReturnType.isNull()) {
7347 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7348 Builder.AddTextChunk("BOOL");
7349 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7350 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007351
Fangrui Song050229d2018-11-24 00:14:31 +00007352 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007353 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007354 CXCursor_ObjCInstanceMethodDecl));
7355 }
7356 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007357
Douglas Gregor669a25a2011-02-17 00:22:45 +00007358 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007359 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007360 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007361 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007362 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007363 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007364 if (ReturnType.isNull()) {
7365 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7366 Builder.AddTextChunk("void");
7367 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7368 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007369
Fangrui Song050229d2018-11-24 00:14:31 +00007370 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007371 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007372 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7373 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007374 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007375 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007376 CXCursor_ObjCInstanceMethodDecl));
7377 }
7378 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007379
Douglas Gregor669a25a2011-02-17 00:22:45 +00007380 // Indexed and unordered accessors
7381 unsigned IndexedGetterPriority = CCP_CodePattern;
7382 unsigned IndexedSetterPriority = CCP_CodePattern;
7383 unsigned UnorderedGetterPriority = CCP_CodePattern;
7384 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007385 if (const auto *ObjCPointer =
7386 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007387 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7388 // If this interface type is not provably derived from a known
7389 // collection, penalize the corresponding completions.
7390 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007391 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007392 if (!InheritsFromClassNamed(IFace, "NSArray"))
7393 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7394 }
7395
7396 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007397 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007398 if (!InheritsFromClassNamed(IFace, "NSSet"))
7399 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7400 }
7401 }
7402 } else {
7403 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7404 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7405 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7406 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7407 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007408
Douglas Gregor669a25a2011-02-17 00:22:45 +00007409 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007410 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007411 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007412 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007413 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007414 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7415 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007416 if (ReturnType.isNull()) {
7417 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7418 Builder.AddTextChunk("NSUInteger");
7419 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007421
Fangrui Song050229d2018-11-24 00:14:31 +00007422 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7423 Results.AddResult(
7424 Result(Builder.TakeString(),
7425 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7426 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007427 }
7428 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007429
Douglas Gregor669a25a2011-02-17 00:22:45 +00007430 // Indexed getters
7431 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7432 if (IsInstanceMethod &&
7433 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007434 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007435 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007436 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007437 if (ReturnType.isNull()) {
7438 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7439 Builder.AddTextChunk("id");
7440 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7441 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007442
Douglas Gregor669a25a2011-02-17 00:22:45 +00007443 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7445 Builder.AddTextChunk("NSUInteger");
7446 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7447 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007448 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007449 CXCursor_ObjCInstanceMethodDecl));
7450 }
7451 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007452
Douglas Gregor669a25a2011-02-17 00:22:45 +00007453 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7454 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007455 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007456 (ReturnType->isObjCObjectPointerType() &&
7457 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007458 ReturnType->getAs<ObjCObjectPointerType>()
7459 ->getInterfaceDecl()
7460 ->getName() == "NSArray"))) {
7461 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007462 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007463 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007464 if (ReturnType.isNull()) {
7465 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7466 Builder.AddTextChunk("NSArray *");
7467 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7468 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007469
Douglas Gregor669a25a2011-02-17 00:22:45 +00007470 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7471 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7472 Builder.AddTextChunk("NSIndexSet *");
7473 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7474 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007475 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007476 CXCursor_ObjCInstanceMethodDecl));
7477 }
7478 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007479
Douglas Gregor669a25a2011-02-17 00:22:45 +00007480 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7481 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007482 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007483 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7484 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007485
David Blaikie82e95a32014-11-19 07:49:47 +00007486 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007487 if (ReturnType.isNull()) {
7488 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7489 Builder.AddTextChunk("void");
7490 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7491 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007492
Douglas Gregor669a25a2011-02-17 00:22:45 +00007493 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7494 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7495 Builder.AddPlaceholderChunk("object-type");
7496 Builder.AddTextChunk(" **");
7497 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7498 Builder.AddTextChunk("buffer");
7499 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7500 Builder.AddTypedTextChunk("range:");
7501 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7502 Builder.AddTextChunk("NSRange");
7503 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7504 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007505 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007506 CXCursor_ObjCInstanceMethodDecl));
7507 }
7508 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007509
Douglas Gregor669a25a2011-02-17 00:22:45 +00007510 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007511
Douglas Gregor669a25a2011-02-17 00:22:45 +00007512 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7513 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007514 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007515 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7516 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007517
David Blaikie82e95a32014-11-19 07:49:47 +00007518 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007519 if (ReturnType.isNull()) {
7520 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7521 Builder.AddTextChunk("void");
7522 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7523 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007524
Douglas Gregor669a25a2011-02-17 00:22:45 +00007525 Builder.AddTypedTextChunk("insertObject:");
7526 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7527 Builder.AddPlaceholderChunk("object-type");
7528 Builder.AddTextChunk(" *");
7529 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7530 Builder.AddTextChunk("object");
7531 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7532 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7533 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7534 Builder.AddPlaceholderChunk("NSUInteger");
7535 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7536 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007537 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007538 CXCursor_ObjCInstanceMethodDecl));
7539 }
7540 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007541
Douglas Gregor669a25a2011-02-17 00:22:45 +00007542 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7543 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007544 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007545 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7546 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007547
David Blaikie82e95a32014-11-19 07:49:47 +00007548 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007549 if (ReturnType.isNull()) {
7550 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7551 Builder.AddTextChunk("void");
7552 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7553 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007554
Douglas Gregor669a25a2011-02-17 00:22:45 +00007555 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7556 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7557 Builder.AddTextChunk("NSArray *");
7558 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7559 Builder.AddTextChunk("array");
7560 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7561 Builder.AddTypedTextChunk("atIndexes:");
7562 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7563 Builder.AddPlaceholderChunk("NSIndexSet *");
7564 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7565 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007566 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007567 CXCursor_ObjCInstanceMethodDecl));
7568 }
7569 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007570
Douglas Gregor669a25a2011-02-17 00:22:45 +00007571 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7572 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007573 std::string SelectorName =
7574 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007575 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007576 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007577 if (ReturnType.isNull()) {
7578 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7579 Builder.AddTextChunk("void");
7580 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7581 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007582
Douglas Gregor669a25a2011-02-17 00:22:45 +00007583 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7584 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7585 Builder.AddTextChunk("NSUInteger");
7586 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7587 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007588 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007589 CXCursor_ObjCInstanceMethodDecl));
7590 }
7591 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007592
Douglas Gregor669a25a2011-02-17 00:22:45 +00007593 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7594 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007595 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007596 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007597 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007598 if (ReturnType.isNull()) {
7599 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7600 Builder.AddTextChunk("void");
7601 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7602 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007603
Douglas Gregor669a25a2011-02-17 00:22:45 +00007604 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7605 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7606 Builder.AddTextChunk("NSIndexSet *");
7607 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7608 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007609 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007610 CXCursor_ObjCInstanceMethodDecl));
7611 }
7612 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007613
Douglas Gregor669a25a2011-02-17 00:22:45 +00007614 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7615 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007616 std::string SelectorName =
7617 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7618 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7619 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007620
David Blaikie82e95a32014-11-19 07:49:47 +00007621 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007622 if (ReturnType.isNull()) {
7623 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7624 Builder.AddTextChunk("void");
7625 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7626 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007627
Douglas Gregor669a25a2011-02-17 00:22:45 +00007628 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7629 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7630 Builder.AddPlaceholderChunk("NSUInteger");
7631 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7632 Builder.AddTextChunk("index");
7633 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7634 Builder.AddTypedTextChunk("withObject:");
7635 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7636 Builder.AddTextChunk("id");
7637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7638 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007639 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007640 CXCursor_ObjCInstanceMethodDecl));
7641 }
7642 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007643
Douglas Gregor669a25a2011-02-17 00:22:45 +00007644 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7645 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007646 std::string SelectorName1 =
7647 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007648 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007649 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7650 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007651
David Blaikie82e95a32014-11-19 07:49:47 +00007652 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007653 if (ReturnType.isNull()) {
7654 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7655 Builder.AddTextChunk("void");
7656 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7657 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007658
Douglas Gregor669a25a2011-02-17 00:22:45 +00007659 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7660 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7661 Builder.AddPlaceholderChunk("NSIndexSet *");
7662 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7663 Builder.AddTextChunk("indexes");
7664 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7665 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7666 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7667 Builder.AddTextChunk("NSArray *");
7668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7669 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007670 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007671 CXCursor_ObjCInstanceMethodDecl));
7672 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007673 }
7674
Douglas Gregor669a25a2011-02-17 00:22:45 +00007675 // Unordered getters
7676 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007677 if (IsInstanceMethod &&
7678 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007679 (ReturnType->isObjCObjectPointerType() &&
7680 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007681 ReturnType->getAs<ObjCObjectPointerType>()
7682 ->getInterfaceDecl()
7683 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007684 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007685 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007686 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7687 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007688 if (ReturnType.isNull()) {
7689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7690 Builder.AddTextChunk("NSEnumerator *");
7691 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7692 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007693
Douglas Gregor669a25a2011-02-17 00:22:45 +00007694 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007695 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007696 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007697 }
7698 }
7699
7700 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007701 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007702 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007703 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007704 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007705 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007706 if (ReturnType.isNull()) {
7707 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7708 Builder.AddPlaceholderChunk("object-type");
7709 Builder.AddTextChunk(" *");
7710 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7711 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007712
Douglas Gregor669a25a2011-02-17 00:22:45 +00007713 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7714 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7715 if (ReturnType.isNull()) {
7716 Builder.AddPlaceholderChunk("object-type");
7717 Builder.AddTextChunk(" *");
7718 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007719 Builder.AddTextChunk(GetCompletionTypeString(
7720 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007721 }
7722 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7723 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007724 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007725 CXCursor_ObjCInstanceMethodDecl));
7726 }
7727 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007728
Douglas Gregor669a25a2011-02-17 00:22:45 +00007729 // Mutable unordered accessors
7730 // - (void)addKeyObject:(type *)object
7731 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007732 std::string SelectorName =
7733 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007734 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007735 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007736 if (ReturnType.isNull()) {
7737 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7738 Builder.AddTextChunk("void");
7739 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7740 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007741
Douglas Gregor669a25a2011-02-17 00:22:45 +00007742 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7743 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7744 Builder.AddPlaceholderChunk("object-type");
7745 Builder.AddTextChunk(" *");
7746 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7747 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007748 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007749 CXCursor_ObjCInstanceMethodDecl));
7750 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007751 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007752
7753 // - (void)addKey:(NSSet *)objects
7754 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007755 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007756 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007757 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007758 if (ReturnType.isNull()) {
7759 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7760 Builder.AddTextChunk("void");
7761 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7762 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007763
Douglas Gregor669a25a2011-02-17 00:22:45 +00007764 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7765 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7766 Builder.AddTextChunk("NSSet *");
7767 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7768 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007769 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007770 CXCursor_ObjCInstanceMethodDecl));
7771 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007772 }
7773
Douglas Gregor669a25a2011-02-17 00:22:45 +00007774 // - (void)removeKeyObject:(type *)object
7775 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007776 std::string SelectorName =
7777 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007778 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007779 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007780 if (ReturnType.isNull()) {
7781 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7782 Builder.AddTextChunk("void");
7783 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7784 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007785
Douglas Gregor669a25a2011-02-17 00:22:45 +00007786 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7787 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7788 Builder.AddPlaceholderChunk("object-type");
7789 Builder.AddTextChunk(" *");
7790 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7791 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007792 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007793 CXCursor_ObjCInstanceMethodDecl));
7794 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007795 }
7796
Douglas Gregor669a25a2011-02-17 00:22:45 +00007797 // - (void)removeKey:(NSSet *)objects
7798 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007799 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007800 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007801 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007802 if (ReturnType.isNull()) {
7803 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7804 Builder.AddTextChunk("void");
7805 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7806 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007807
Douglas Gregor669a25a2011-02-17 00:22:45 +00007808 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7809 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7810 Builder.AddTextChunk("NSSet *");
7811 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7812 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007813 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007814 CXCursor_ObjCInstanceMethodDecl));
7815 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007816 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007817
7818 // - (void)intersectKey:(NSSet *)objects
7819 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007820 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007821 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007822 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007823 if (ReturnType.isNull()) {
7824 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7825 Builder.AddTextChunk("void");
7826 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7827 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007828
Douglas Gregor669a25a2011-02-17 00:22:45 +00007829 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7830 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7831 Builder.AddTextChunk("NSSet *");
7832 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7833 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007834 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007835 CXCursor_ObjCInstanceMethodDecl));
7836 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007837 }
7838
Douglas Gregor669a25a2011-02-17 00:22:45 +00007839 // Key-Value Observing
7840 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007841 if (!IsInstanceMethod &&
7842 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007843 (ReturnType->isObjCObjectPointerType() &&
7844 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007845 ReturnType->getAs<ObjCObjectPointerType>()
7846 ->getInterfaceDecl()
7847 ->getName() == "NSSet"))) {
7848 std::string SelectorName =
7849 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007850 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007851 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7852 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007853 if (ReturnType.isNull()) {
7854 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007855 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7857 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007858
Douglas Gregor669a25a2011-02-17 00:22:45 +00007859 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007860 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007861 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00007862 }
7863 }
7864
7865 // + (BOOL)automaticallyNotifiesObserversForKey
7866 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00007867 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007868 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007869 std::string SelectorName =
7870 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007871 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007872 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7873 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007874 if (ReturnType.isNull()) {
7875 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7876 Builder.AddTextChunk("BOOL");
7877 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7878 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007879
Douglas Gregor857bcda2011-06-02 04:02:27 +00007880 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007881 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007882 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007883 }
7884 }
7885}
7886
Alex Lorenzb8740422017-10-24 16:39:37 +00007887void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007888 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007889 // Determine the return type of the method we're declaring, if
7890 // provided.
7891 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007892 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007893 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007894 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7895 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007896 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007897 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007898 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007899 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007900 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007901 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7902 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007903 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00007904 } else if (ObjCCategoryImplDecl *CatImpl =
7905 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007906 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007907 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007908 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007909 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007910 }
7911
7912 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007913 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007914 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007915 }
7916
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007917 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007918 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00007919 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007920 return;
7921 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007922
Douglas Gregor636a61e2010-04-07 00:21:17 +00007923 // Find all of the methods that we could declare/implement here.
7924 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00007925 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
7926 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007927
Douglas Gregor636a61e2010-04-07 00:21:17 +00007928 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007929 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007930 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007931 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007932 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007933 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007934 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007935 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007936 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007937 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007938 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007939 CodeCompletionBuilder Builder(Results.getAllocator(),
7940 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007941
7942 // Add the '-'/'+' prefix if it wasn't provided yet.
7943 if (!IsInstanceMethod) {
7944 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7945 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7946 }
7947
Douglas Gregor636a61e2010-04-07 00:21:17 +00007948 // If the result type was not already provided, add it to the
7949 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007950 if (ReturnType.isNull()) {
7951 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7952 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00007953 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
7954 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007955 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007956
7957 Selector Sel = Method->getSelector();
7958
7959 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00007960 Builder.AddTypedTextChunk(
7961 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007962
7963 // Add parameters to the pattern.
7964 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007965 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007966 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007967 P != PEnd; (void)++P, ++I) {
7968 // Add the part of the selector name.
7969 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007970 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007971 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007972 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7973 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00007974 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007975 } else
7976 break;
7977
7978 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007979 QualType ParamType;
7980 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7981 ParamType = (*P)->getType();
7982 else
7983 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00007984 ParamType = ParamType.substObjCTypeArgs(
7985 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007986 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00007987 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
7988 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007989
Douglas Gregor636a61e2010-04-07 00:21:17 +00007990 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00007991 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007992 }
7993
7994 if (Method->isVariadic()) {
7995 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007996 Builder.AddChunk(CodeCompletionString::CK_Comma);
7997 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007998 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007999
Douglas Gregord37c59d2010-05-28 00:57:46 +00008000 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008001 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008002 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8003 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8004 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008005 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008006 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008007 Builder.AddTextChunk("return");
8008 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8009 Builder.AddPlaceholderChunk("expression");
8010 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008011 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008012 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008013
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008014 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8015 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008016 }
8017
Douglas Gregor416b5752010-08-25 01:08:01 +00008018 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008019 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008020 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008021 setInBaseClass(R);
8022 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008023 }
8024
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008025 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008026 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008027 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008028 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008029 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008030
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008031 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008032 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008033 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008034 M != MEnd; ++M)
8035 KnownSelectors.insert(M->first);
8036
Douglas Gregor669a25a2011-02-17 00:22:45 +00008037 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8038 if (!IFace)
8039 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8040 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008041
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008042 if (IFace)
8043 for (auto *Cat : IFace->visible_categories())
8044 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008045
8046 if (IsInstanceMethod) {
8047 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8048 for (auto *P : Containers[I]->instance_properties())
8049 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8050 KnownSelectors, Results);
8051 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008052 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008053
Douglas Gregor636a61e2010-04-07 00:21:17 +00008054 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008055
8056 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8057 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008058}
Douglas Gregor95887f92010-07-08 23:20:03 +00008059
Fangrui Song050229d2018-11-24 00:14:31 +00008060void Sema::CodeCompleteObjCMethodDeclSelector(
8061 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8062 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008063 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008064 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008065 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008066 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8067 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008068 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008069 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008070 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008071
8072 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008073 }
8074 }
8075
8076 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008077 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008078 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008079 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008080 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008081
Douglas Gregor95887f92010-07-08 23:20:03 +00008082 if (ReturnTy)
8083 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008084
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008085 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008086 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8087 MEnd = MethodPool.end();
8088 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008089 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8090 : &M->second.second;
8091 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008092 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008093 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008094
Douglas Gregor45879692010-07-08 23:37:41 +00008095 if (AtParameterName) {
8096 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008097 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008098 if (NumSelIdents &&
8099 NumSelIdents <= MethList->getMethod()->param_size()) {
8100 ParmVarDecl *Param =
8101 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008102 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008103 CodeCompletionBuilder Builder(Results.getAllocator(),
8104 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008105 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008106 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008107 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008108 }
8109 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008110
Douglas Gregor45879692010-07-08 23:37:41 +00008111 continue;
8112 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008113
Nico Weber2e0c8f72014-12-27 03:58:08 +00008114 Result R(MethList->getMethod(),
8115 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008116 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008117 R.AllParametersAreInformative = false;
8118 R.DeclaringEntity = true;
8119 Results.MaybeAddResult(R, CurContext);
8120 }
8121 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008122
Douglas Gregor95887f92010-07-08 23:20:03 +00008123 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008124
8125 if (!AtParameterName && !SelIdents.empty() &&
8126 SelIdents.front()->getName().startswith("init")) {
8127 for (const auto &M : PP.macros()) {
8128 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8129 continue;
8130 Results.EnterNewScope();
8131 CodeCompletionBuilder Builder(Results.getAllocator(),
8132 Results.getCodeCompletionTUInfo());
8133 Builder.AddTypedTextChunk(
8134 Builder.getAllocator().CopyString(M.first->getName()));
8135 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8136 CXCursor_MacroDefinition));
8137 Results.ExitScope();
8138 }
8139 }
8140
Eric Liuf5ba09f2018-07-04 10:01:18 +00008141 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8142 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008143}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008144
Douglas Gregorec00a262010-08-24 22:20:20 +00008145void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008146 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008147 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008148 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008149 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008150
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008151 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008152 CodeCompletionBuilder Builder(Results.getAllocator(),
8153 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008154 Builder.AddTypedTextChunk("if");
8155 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8156 Builder.AddPlaceholderChunk("condition");
8157 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008158
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008159 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008160 Builder.AddTypedTextChunk("ifdef");
8161 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8162 Builder.AddPlaceholderChunk("macro");
8163 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008164
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008165 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008166 Builder.AddTypedTextChunk("ifndef");
8167 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8168 Builder.AddPlaceholderChunk("macro");
8169 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008170
8171 if (InConditional) {
8172 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008173 Builder.AddTypedTextChunk("elif");
8174 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8175 Builder.AddPlaceholderChunk("condition");
8176 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008177
8178 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008179 Builder.AddTypedTextChunk("else");
8180 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008181
8182 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008183 Builder.AddTypedTextChunk("endif");
8184 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008185 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008186
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008187 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008188 Builder.AddTypedTextChunk("include");
8189 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8190 Builder.AddTextChunk("\"");
8191 Builder.AddPlaceholderChunk("header");
8192 Builder.AddTextChunk("\"");
8193 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008194
8195 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008196 Builder.AddTypedTextChunk("include");
8197 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8198 Builder.AddTextChunk("<");
8199 Builder.AddPlaceholderChunk("header");
8200 Builder.AddTextChunk(">");
8201 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008202
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008203 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008204 Builder.AddTypedTextChunk("define");
8205 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8206 Builder.AddPlaceholderChunk("macro");
8207 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008208
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008209 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008210 Builder.AddTypedTextChunk("define");
8211 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8212 Builder.AddPlaceholderChunk("macro");
8213 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8214 Builder.AddPlaceholderChunk("args");
8215 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8216 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008217
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008218 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008219 Builder.AddTypedTextChunk("undef");
8220 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8221 Builder.AddPlaceholderChunk("macro");
8222 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008223
8224 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008225 Builder.AddTypedTextChunk("line");
8226 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8227 Builder.AddPlaceholderChunk("number");
8228 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008229
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008230 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008231 Builder.AddTypedTextChunk("line");
8232 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8233 Builder.AddPlaceholderChunk("number");
8234 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8235 Builder.AddTextChunk("\"");
8236 Builder.AddPlaceholderChunk("filename");
8237 Builder.AddTextChunk("\"");
8238 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008239
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008240 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008241 Builder.AddTypedTextChunk("error");
8242 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8243 Builder.AddPlaceholderChunk("message");
8244 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008245
8246 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008247 Builder.AddTypedTextChunk("pragma");
8248 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8249 Builder.AddPlaceholderChunk("arguments");
8250 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008251
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008252 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008253 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008254 Builder.AddTypedTextChunk("import");
8255 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8256 Builder.AddTextChunk("\"");
8257 Builder.AddPlaceholderChunk("header");
8258 Builder.AddTextChunk("\"");
8259 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008260
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008261 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008262 Builder.AddTypedTextChunk("import");
8263 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8264 Builder.AddTextChunk("<");
8265 Builder.AddPlaceholderChunk("header");
8266 Builder.AddTextChunk(">");
8267 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008268 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008269
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008270 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008271 Builder.AddTypedTextChunk("include_next");
8272 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8273 Builder.AddTextChunk("\"");
8274 Builder.AddPlaceholderChunk("header");
8275 Builder.AddTextChunk("\"");
8276 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008277
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008278 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008279 Builder.AddTypedTextChunk("include_next");
8280 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8281 Builder.AddTextChunk("<");
8282 Builder.AddPlaceholderChunk("header");
8283 Builder.AddTextChunk(">");
8284 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008285
8286 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008287 Builder.AddTypedTextChunk("warning");
8288 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8289 Builder.AddPlaceholderChunk("message");
8290 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008291
8292 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8293 // completions for them. And __include_macros is a Clang-internal extension
8294 // that we don't want to encourage anyone to use.
8295
8296 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8297 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008298
8299 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008300 Results.data(), Results.size());
8301}
8302
8303void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008304 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8305 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008306}
8307
Douglas Gregorec00a262010-08-24 22:20:20 +00008308void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008309 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008310 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008311 IsDefinition ? CodeCompletionContext::CCC_MacroName
8312 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008313 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008314 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008315 CodeCompletionBuilder Builder(Results.getAllocator(),
8316 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008317 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008318 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008319 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008320 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008321 Builder.AddTypedTextChunk(
8322 Builder.getAllocator().CopyString(M->first->getName()));
8323 Results.AddResult(CodeCompletionResult(
8324 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008325 }
8326 Results.ExitScope();
8327 } else if (IsDefinition) {
8328 // FIXME: Can we detect when the user just wrote an include guard above?
8329 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008330
Douglas Gregor0ac41382010-09-23 23:01:17 +00008331 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008332 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008333}
8334
Douglas Gregorec00a262010-08-24 22:20:20 +00008335void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008336 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008337 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008338 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008339
Douglas Gregorec00a262010-08-24 22:20:20 +00008340 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008341 AddMacroResults(PP, Results,
8342 CodeCompleter ? CodeCompleter->loadExternal() : false,
8343 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008344
Fangrui Song050229d2018-11-24 00:14:31 +00008345 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008346 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008347 CodeCompletionBuilder Builder(Results.getAllocator(),
8348 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008349 Builder.AddTypedTextChunk("defined");
8350 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8351 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8352 Builder.AddPlaceholderChunk("macro");
8353 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8354 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008355 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008356
8357 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8358 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008359}
8360
8361void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8362 IdentifierInfo *Macro,
8363 MacroInfo *MacroInfo,
8364 unsigned Argument) {
8365 // FIXME: In the future, we could provide "overload" results, much like we
8366 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008367
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008368 // Now just ignore this. There will be another code-completion callback
8369 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008370}
8371
Sam McCall3d8051a2018-09-18 08:40:41 +00008372// This handles completion inside an #include filename, e.g. #include <foo/ba
8373// We look for the directory "foo" under each directory on the include path,
8374// list its files, and reassemble the appropriate #include.
8375void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8376 // RelDir should use /, but unescaped \ is possible on windows!
8377 // Our completions will normalize to / for simplicity, this case is rare.
8378 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8379 // We need the native slashes for the actual file system interactions.
8380 SmallString<128> NativeRelDir = StringRef(RelDir);
8381 llvm::sys::path::native(NativeRelDir);
8382 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8383
8384 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8385 CodeCompleter->getCodeCompletionTUInfo(),
8386 CodeCompletionContext::CCC_IncludedFile);
8387 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8388
8389 // Helper: adds one file or directory completion result.
8390 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8391 SmallString<64> TypedChunk = Filename;
8392 // Directory completion is up to the slash, e.g. <sys/
8393 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8394 auto R = SeenResults.insert(TypedChunk);
8395 if (R.second) { // New completion
8396 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8397 *R.first = InternedTyped; // Avoid dangling StringRef.
8398 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8399 CodeCompleter->getCodeCompletionTUInfo());
8400 Builder.AddTypedTextChunk(InternedTyped);
8401 // The result is a "Pattern", which is pretty opaque.
8402 // We may want to include the real filename to allow smart ranking.
8403 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8404 }
8405 };
8406
8407 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008408 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8409 bool IsSystem,
8410 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008411 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008412 if (!NativeRelDir.empty()) {
8413 if (LookupType == DirectoryLookup::LT_Framework) {
8414 // For a framework dir, #include <Foo/Bar/> actually maps to
8415 // a path of Foo.framework/Headers/Bar/.
8416 auto Begin = llvm::sys::path::begin(NativeRelDir);
8417 auto End = llvm::sys::path::end(NativeRelDir);
8418
8419 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8420 llvm::sys::path::append(Dir, ++Begin, End);
8421 } else {
8422 llvm::sys::path::append(Dir, NativeRelDir);
8423 }
8424 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008425
8426 std::error_code EC;
8427 unsigned Count = 0;
8428 for (auto It = FS->dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008429 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008430 if (++Count == 2500) // If we happen to hit a huge directory,
8431 break; // bail out early so we're not too slow.
8432 StringRef Filename = llvm::sys::path::filename(It->path());
8433 switch (It->type()) {
8434 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008435 // All entries in a framework directory must have a ".framework" suffix,
8436 // but the suffix does not appear in the source code's include/import.
8437 if (LookupType == DirectoryLookup::LT_Framework &&
8438 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8439 break;
8440
Sam McCall3d8051a2018-09-18 08:40:41 +00008441 AddCompletion(Filename, /*IsDirectory=*/true);
8442 break;
8443 case llvm::sys::fs::file_type::regular_file:
8444 // Only files that really look like headers. (Except in system dirs).
8445 if (!IsSystem) {
8446 // Header extensions from Types.def, which we can't depend on here.
8447 if (!(Filename.endswith_lower(".h") ||
8448 Filename.endswith_lower(".hh") ||
8449 Filename.endswith_lower(".hpp") ||
8450 Filename.endswith_lower(".inc")))
8451 break;
8452 }
8453 AddCompletion(Filename, /*IsDirectory=*/false);
8454 break;
8455 default:
8456 break;
8457 }
8458 }
8459 };
8460
8461 // Helper: adds results relative to IncludeDir, if possible.
8462 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8463 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008464 switch (IncludeDir.getLookupType()) {
8465 case DirectoryLookup::LT_HeaderMap:
8466 // header maps are not (currently) enumerable.
8467 break;
8468 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008469 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8470 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008471 break;
8472 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008473 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8474 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008475 break;
8476 }
8477 };
8478
8479 // Finally with all our helpers, we can scan the include path.
8480 // Do this in standard order so deduplication keeps the right file.
8481 // (In case we decide to add more details to the results later).
8482 const auto &S = PP.getHeaderSearchInfo();
8483 using llvm::make_range;
8484 if (!Angled) {
8485 // The current directory is on the include path for "quoted" includes.
8486 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8487 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008488 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8489 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008490 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8491 AddFilesFromDirLookup(D, false);
8492 }
8493 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008494 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008495 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8496 AddFilesFromDirLookup(D, true);
8497
8498 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8499 Results.data(), Results.size());
8500}
8501
Douglas Gregor11583702010-08-25 17:04:25 +00008502void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008503 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008504 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8505 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008506}
8507
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008508void Sema::CodeCompleteAvailabilityPlatformName() {
8509 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8510 CodeCompleter->getCodeCompletionTUInfo(),
8511 CodeCompletionContext::CCC_Other);
8512 Results.EnterNewScope();
8513 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8514 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8515 Results.AddResult(CodeCompletionResult(Platform));
8516 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8517 Twine(Platform) + "ApplicationExtension")));
8518 }
8519 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008520 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8521 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008522}
8523
Fangrui Song050229d2018-11-24 00:14:31 +00008524void Sema::GatherGlobalCodeCompletions(
8525 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8526 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008527 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8528 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008529 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008530 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008531 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008532 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8533 Consumer,
8534 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008535 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008536
Douglas Gregorb14904c2010-08-13 22:48:40 +00008537 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008538 AddMacroResults(PP, Builder,
8539 CodeCompleter ? CodeCompleter->loadExternal() : false,
8540 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008541
Douglas Gregorb14904c2010-08-13 22:48:40 +00008542 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008543 Results.insert(Results.end(), Builder.data(),
8544 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008545}