blob: 8d953308d818ae977db06561ef1843e99f826b09 [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) {
Sam McCallbc7ff892019-04-04 11:34:18 +00002608 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.
2609 // It would be better to pass in the param Type, which is usually avaliable.
2610 // But this case is rare, so just pretend we fell back to int as elsewhere.
2611 if (!Param)
2612 return "int";
Douglas Gregore90dd002010-08-24 16:15:59 +00002613 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2614 if (Param->getType()->isDependentType() ||
2615 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002616 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002617 // containing that parameter's type.
2618 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002619
Douglas Gregor981a0c42010-08-29 19:47:46 +00002620 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002621 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002622
Douglas Gregor86b42682015-06-19 18:27:52 +00002623 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002624 if (ObjCSubsts)
2625 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2626 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002627 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002628 Result =
2629 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002630 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002631 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002632 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002633 } else {
2634 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002635 }
2636 return Result;
2637 }
Alex Lorenza1951202016-10-18 10:35:27 +00002638
Douglas Gregore90dd002010-08-24 16:15:59 +00002639 // The argument for a block pointer parameter is a block literal with
2640 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002641 FunctionTypeLoc Block;
2642 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002643 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2644 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002645 // Try to retrieve the block type information from the property if this is a
2646 // parameter in a setter.
2647 if (!Block && ObjCMethodParam &&
2648 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2649 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2650 ->findPropertyDecl(/*CheckOverrides=*/false))
2651 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2652 SuppressBlock);
2653 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002654
2655 if (!Block) {
2656 // We were unable to find a FunctionProtoTypeLoc with parameter names
2657 // for the block; just use the parameter type as a placeholder.
2658 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002659 if (!ObjCMethodParam && Param->getIdentifier())
2660 Result = Param->getIdentifier()->getName();
2661
Douglas Gregor86b42682015-06-19 18:27:52 +00002662 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002663
Douglas Gregore90dd002010-08-24 16:15:59 +00002664 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002665 Result = Type.getAsString(Policy);
2666 std::string Quals =
2667 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2668 if (!Quals.empty())
2669 Result = "(" + Quals + " " + Result + ")";
2670 if (Result.back() != ')')
2671 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002672 if (Param->getIdentifier())
2673 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002674 } else {
2675 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002676 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002677
Douglas Gregore90dd002010-08-24 16:15:59 +00002678 return Result;
2679 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002680
Douglas Gregore90dd002010-08-24 16:15:59 +00002681 // We have the function prototype behind the block pointer type, as it was
2682 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002683 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2684 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002685 ObjCSubsts);
2686}
2687
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002688/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002689/// declaration.
2690///
2691/// \param BlockDecl A declaration with an Objective-C block type.
2692///
2693/// \param Block The most relevant type location for that block type.
2694///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002695/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002696/// declaration is included in the resulting string.
2697static std::string
2698formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2699 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002700 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002701 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002702 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002703 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002704 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002705 ResultType =
2706 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2707 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002708 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002709 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002710
2711 // Format the parameter list.
2712 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002713 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002714 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002715 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002716 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002717 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002718 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002719 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002720 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002721 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002722 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002723 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002724 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002725 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002726
David Blaikie6adc78e2013-02-18 22:06:02 +00002727 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002728 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002729 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002730 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002731 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002732
Douglas Gregord793e7c2011-10-18 04:23:19 +00002733 if (SuppressBlock) {
2734 // Format as a parameter.
2735 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002736 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002737 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002738 Result += ")";
2739 Result += Params;
2740 } else {
2741 // Format as a block literal argument.
2742 Result = '^' + Result;
2743 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002744
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002745 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002746 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002747 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002748
Douglas Gregore90dd002010-08-24 16:15:59 +00002749 return Result;
2750}
2751
Erik Verbruggen11338c52017-07-19 10:45:40 +00002752static std::string GetDefaultValueString(const ParmVarDecl *Param,
2753 const SourceManager &SM,
2754 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002755 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002756 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2757 bool Invalid = CharSrcRange.isInvalid();
2758 if (Invalid)
2759 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002760 StringRef srcText =
2761 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002762 if (Invalid)
2763 return "";
2764
2765 if (srcText.empty() || srcText == "=") {
2766 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002767 // This happens if the code is incorrect (for example class is forward
2768 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002769 return "";
2770 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002771 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002772 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2773 // this value always has (or always does not have) '=' in front of it
2774 if (DefValue.at(0) != '=') {
2775 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002776 // Lexer returns built-in types values without '=' and user-defined types
2777 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002778 return " = " + DefValue;
2779 }
2780 return " " + DefValue;
2781}
2782
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002783/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002784static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002785 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002786 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002787 CodeCompletionBuilder &Result,
2788 unsigned Start = 0,
2789 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002790 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002791
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002792 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002793 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002794
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002795 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002796 // When we see an optional default argument, put that argument and
2797 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002798 CodeCompletionBuilder Opt(Result.getAllocator(),
2799 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002800 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002801 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002802 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002803 Result.AddOptionalChunk(Opt.TakeString());
2804 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002805 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002806
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002807 if (FirstParameter)
2808 FirstParameter = false;
2809 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002810 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002811
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002812 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002813
Douglas Gregor3545ff42009-09-21 16:56:56 +00002814 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002815 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002816 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002817 PlaceholderStr +=
2818 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002819
Douglas Gregor400f5972010-08-31 05:13:43 +00002820 if (Function->isVariadic() && P == N - 1)
2821 PlaceholderStr += ", ...";
2822
Douglas Gregor3545ff42009-09-21 16:56:56 +00002823 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002824 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002825 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002826 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002827
Fangrui Song050229d2018-11-24 00:14:31 +00002828 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002829 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002830 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002831 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002832
Richard Smith20e883e2015-04-29 23:20:19 +00002833 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002834 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002835}
2836
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002837/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002838static void AddTemplateParameterChunks(
2839 ASTContext &Context, const PrintingPolicy &Policy,
2840 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2841 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002842 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002843
2844 // Prefer to take the template parameter names from the first declaration of
2845 // the template.
2846 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2847
Douglas Gregor3545ff42009-09-21 16:56:56 +00002848 TemplateParameterList *Params = Template->getTemplateParameters();
2849 TemplateParameterList::iterator PEnd = Params->end();
2850 if (MaxParameters)
2851 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002852 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2853 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002854 bool HasDefaultArg = false;
2855 std::string PlaceholderStr;
2856 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2857 if (TTP->wasDeclaredWithTypename())
2858 PlaceholderStr = "typename";
2859 else
2860 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002861
Douglas Gregor3545ff42009-09-21 16:56:56 +00002862 if (TTP->getIdentifier()) {
2863 PlaceholderStr += ' ';
2864 PlaceholderStr += TTP->getIdentifier()->getName();
2865 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002866
Douglas Gregor3545ff42009-09-21 16:56:56 +00002867 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002868 } else if (NonTypeTemplateParmDecl *NTTP =
2869 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002870 if (NTTP->getIdentifier())
2871 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002872 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002873 HasDefaultArg = NTTP->hasDefaultArgument();
2874 } else {
2875 assert(isa<TemplateTemplateParmDecl>(*P));
2876 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002877
Douglas Gregor3545ff42009-09-21 16:56:56 +00002878 // Since putting the template argument list into the placeholder would
2879 // be very, very long, we just use an abbreviation.
2880 PlaceholderStr = "template<...> class";
2881 if (TTP->getIdentifier()) {
2882 PlaceholderStr += ' ';
2883 PlaceholderStr += TTP->getIdentifier()->getName();
2884 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002885
Douglas Gregor3545ff42009-09-21 16:56:56 +00002886 HasDefaultArg = TTP->hasDefaultArgument();
2887 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002888
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002889 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002890 // When we see an optional default argument, put that argument and
2891 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002892 CodeCompletionBuilder Opt(Result.getAllocator(),
2893 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002894 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002895 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002896 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002897 P - Params->begin(), true);
2898 Result.AddOptionalChunk(Opt.TakeString());
2899 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002900 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002901
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002902 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002903
Douglas Gregor3545ff42009-09-21 16:56:56 +00002904 if (FirstParameter)
2905 FirstParameter = false;
2906 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002907 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002908
Douglas Gregor3545ff42009-09-21 16:56:56 +00002909 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002910 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002911 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002912 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002913}
2914
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002915/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002916/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002917static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2918 NestedNameSpecifier *Qualifier,
2919 bool QualifierIsInformative,
2920 ASTContext &Context,
2921 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002922 if (!Qualifier)
2923 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002924
Douglas Gregorf2510672009-09-21 19:57:38 +00002925 std::string PrintedNNS;
2926 {
2927 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002928 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002929 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002930 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002931 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002932 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002933 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002934}
2935
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002936static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002937AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002938 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002939 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002940 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00002941 return;
2942
Douglas Gregor304f9b02011-02-01 21:15:40 +00002943 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002944
Douglas Gregor304f9b02011-02-01 21:15:40 +00002945 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002946 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002947 Result.AddInformativeChunk(" const");
2948 return;
2949 }
2950
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002951 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002952 Result.AddInformativeChunk(" volatile");
2953 return;
2954 }
2955
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002956 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002957 Result.AddInformativeChunk(" restrict");
2958 return;
2959 }
2960
2961 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002962 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002963 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002964 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002965 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002966 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002967 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002968 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002969 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002970}
2971
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002972/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002973static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002974 const NamedDecl *ND,
2975 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002976 DeclarationName Name = ND->getDeclName();
2977 if (!Name)
2978 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002979
Douglas Gregor0212fd72010-09-21 16:06:22 +00002980 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002981 case DeclarationName::CXXOperatorName: {
2982 const char *OperatorName = nullptr;
2983 switch (Name.getCXXOverloadedOperator()) {
2984 case OO_None:
2985 case OO_Conditional:
2986 case NUM_OVERLOADED_OPERATORS:
2987 OperatorName = "operator";
2988 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002989
Fangrui Song050229d2018-11-24 00:14:31 +00002990#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
2991 case OO_##Name: \
2992 OperatorName = "operator" Spelling; \
2993 break;
2994#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00002995#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002996
Fangrui Song050229d2018-11-24 00:14:31 +00002997 case OO_New:
2998 OperatorName = "operator new";
2999 break;
3000 case OO_Delete:
3001 OperatorName = "operator delete";
3002 break;
3003 case OO_Array_New:
3004 OperatorName = "operator new[]";
3005 break;
3006 case OO_Array_Delete:
3007 OperatorName = "operator delete[]";
3008 break;
3009 case OO_Call:
3010 OperatorName = "operator()";
3011 break;
3012 case OO_Subscript:
3013 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003014 break;
3015 }
Fangrui Song050229d2018-11-24 00:14:31 +00003016 Result.AddTypedTextChunk(OperatorName);
3017 break;
3018 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003019
Douglas Gregor0212fd72010-09-21 16:06:22 +00003020 case DeclarationName::Identifier:
3021 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003022 case DeclarationName::CXXDestructorName:
3023 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003024 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003025 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003026 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003027
Richard Smith35845152017-02-07 01:37:30 +00003028 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003029 case DeclarationName::CXXUsingDirective:
3030 case DeclarationName::ObjCZeroArgSelector:
3031 case DeclarationName::ObjCOneArgSelector:
3032 case DeclarationName::ObjCMultiArgSelector:
3033 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003034
Douglas Gregor0212fd72010-09-21 16:06:22 +00003035 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003036 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003037 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003038 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003039 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003040 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003041 Record = InjectedTy->getDecl();
3042 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003043 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003044 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003045 break;
3046 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003047
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003048 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003049 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003050 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003051 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003052 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003053 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003054 }
3055 break;
3056 }
3057 }
3058}
3059
Fangrui Song050229d2018-11-24 00:14:31 +00003060CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3061 Sema &S, const CodeCompletionContext &CCContext,
3062 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3063 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003064 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3065 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003066}
3067
Eric Liu00f43c92018-07-06 09:43:57 +00003068CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3069 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3070 CodeCompletionTUInfo &CCTUInfo) {
3071 assert(Kind == RK_Macro);
3072 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3073 const MacroInfo *MI = PP.getMacroInfo(Macro);
3074 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3075
3076 if (!MI || !MI->isFunctionLike())
3077 return Result.TakeString();
3078
3079 // Format a function-like macro with placeholders for the arguments.
3080 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3081 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3082
3083 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3084 if (MI->isC99Varargs()) {
3085 --AEnd;
3086
3087 if (A == AEnd) {
3088 Result.AddPlaceholderChunk("...");
3089 }
3090 }
3091
3092 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3093 if (A != MI->param_begin())
3094 Result.AddChunk(CodeCompletionString::CK_Comma);
3095
3096 if (MI->isVariadic() && (A + 1) == AEnd) {
3097 SmallString<32> Arg = (*A)->getName();
3098 if (MI->isC99Varargs())
3099 Arg += ", ...";
3100 else
3101 Arg += "...";
3102 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3103 break;
3104 }
3105
3106 // Non-variadic macros are simple.
3107 Result.AddPlaceholderChunk(
3108 Result.getAllocator().CopyString((*A)->getName()));
3109 }
3110 Result.AddChunk(CodeCompletionString::CK_RightParen);
3111 return Result.TakeString();
3112}
3113
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003114/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003115/// result.
3116///
3117/// \returns Either a new, heap-allocated code completion string describing
3118/// how to use this result, or NULL to indicate that the string or name of the
3119/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003120CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3121 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3122 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3123 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003124 if (Kind == RK_Macro)
3125 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3126
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003127 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003128
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003129 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003130 if (Kind == RK_Pattern) {
3131 Pattern->Priority = Priority;
3132 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003133
Douglas Gregor78254c82012-03-27 23:34:16 +00003134 if (Declaration) {
3135 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003136 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003137 if (const RawComment *RC =
3138 getPatternCompletionComment(Ctx, Declaration)) {
3139 Result.addBriefComment(RC->getBriefText(Ctx));
3140 Pattern->BriefComment = Result.getBriefComment();
3141 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003142 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003143
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003144 return Pattern;
3145 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003146
Douglas Gregorf09935f2009-12-01 05:55:20 +00003147 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003148 Result.AddTypedTextChunk(Keyword);
3149 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003150 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003151 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003152 return createCodeCompletionStringForDecl(
3153 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003154}
3155
3156CodeCompletionString *
3157CodeCompletionResult::createCodeCompletionStringForOverride(
3158 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3159 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3160 PrintingPolicy &Policy) {
3161 std::string OverrideSignature;
3162 llvm::raw_string_ostream OS(OverrideSignature);
3163 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3164 /*IncludeBriefComments=*/false,
3165 CCContext, Policy);
3166 printOverrideString(OS, CCS);
3167 OS << " override";
3168 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
3169 return Result.TakeString();
3170}
3171
3172CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3173 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3174 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3175 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003176 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003177 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003178
3179 if (IncludeBriefComments) {
3180 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003181 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003182 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003183 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003184 }
3185
Douglas Gregor9eb77012009-11-07 00:00:49 +00003186 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003187 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003188 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003189 Result.AddTextChunk("::");
3190 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003191 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003192
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003193 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3194 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003195
Douglas Gregorc3425b12015-07-07 06:20:19 +00003196 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003197
Fangrui Song050229d2018-11-24 00:14:31 +00003198 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003199 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003200 Ctx, Policy);
3201 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003202 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003203 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003204 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003205 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003206 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003207 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003208
Fangrui Song050229d2018-11-24 00:14:31 +00003209 if (const FunctionTemplateDecl *FunTmpl =
3210 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003211 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003212 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003213 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003214 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003215
Douglas Gregor3545ff42009-09-21 16:56:56 +00003216 // Figure out which template parameters are deduced (or have default
3217 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003218 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003219 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003220 unsigned LastDeducibleArgument;
3221 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3222 --LastDeducibleArgument) {
3223 if (!Deduced[LastDeducibleArgument - 1]) {
3224 // C++0x: Figure out if the template argument has a default. If so,
3225 // the user doesn't need to type this argument.
3226 // FIXME: We need to abstract template parameters better!
3227 bool HasDefaultArg = false;
3228 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003229 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003230 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3231 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003232 else if (NonTypeTemplateParmDecl *NTTP =
3233 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003234 HasDefaultArg = NTTP->hasDefaultArgument();
3235 else {
3236 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003237 HasDefaultArg =
3238 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003239 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003240
Douglas Gregor3545ff42009-09-21 16:56:56 +00003241 if (!HasDefaultArg)
3242 break;
3243 }
3244 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003245
Douglas Gregor3545ff42009-09-21 16:56:56 +00003246 if (LastDeducibleArgument) {
3247 // Some of the function template arguments cannot be deduced from a
3248 // function call, so we introduce an explicit template argument list
3249 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003250 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003251 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003252 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003253 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003254 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003255
Douglas Gregor3545ff42009-09-21 16:56:56 +00003256 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003257 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003258 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003259 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003260 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003261 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003262 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003263
Fangrui Song050229d2018-11-24 00:14:31 +00003264 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003265 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003266 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003267 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003268 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003269 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003270 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003271 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003272 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003273 }
Fangrui Song050229d2018-11-24 00:14:31 +00003274 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003275 Selector Sel = Method->getSelector();
3276 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003277 Result.AddTypedTextChunk(
3278 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003279 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003280 }
3281
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003282 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003283 SelName += ':';
3284 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003285 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003286 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003287 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003288
Douglas Gregor1b605f72009-11-19 01:08:35 +00003289 // If there is only one parameter, and we're past it, add an empty
3290 // typed-text chunk since there is nothing to type.
3291 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003292 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003293 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003294 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003295 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003296 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003297 P != PEnd; (void)++P, ++Idx) {
3298 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003299 std::string Keyword;
3300 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003301 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003302 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003303 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003304 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003305 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003306 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003307 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003308 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003309 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003310
Douglas Gregor1b605f72009-11-19 01:08:35 +00003311 // If we're before the starting parameter, skip the placeholder.
3312 if (Idx < StartParameter)
3313 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003314
3315 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003316 QualType ParamType = (*P)->getType();
3317 Optional<ArrayRef<QualType>> ObjCSubsts;
3318 if (!CCContext.getBaseType().isNull())
3319 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3320
3321 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3322 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003323 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003324 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003325 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003326 ParamType = ParamType.substObjCTypeArgs(
3327 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003328 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003329 ParamType);
3330 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003331 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003332 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003333 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003334 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003335
Douglas Gregor400f5972010-08-31 05:13:43 +00003336 if (Method->isVariadic() && (P + 1) == PEnd)
3337 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003338
Douglas Gregor95887f92010-07-08 23:20:03 +00003339 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003340 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003341 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003342 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003343 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003344 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003345 }
3346
Douglas Gregor04c5f972009-12-23 00:21:46 +00003347 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003348 if (Method->param_size() == 0) {
3349 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003350 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003351 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003352 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003353 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003354 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003355 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003356
Richard Smith20e883e2015-04-29 23:20:19 +00003357 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003358 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003359
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003360 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003361 }
3362
Douglas Gregorf09935f2009-12-01 05:55:20 +00003363 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003364 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003365 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003366
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003367 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003368 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003369 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003370}
3371
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003372const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3373 const NamedDecl *ND) {
3374 if (!ND)
3375 return nullptr;
3376 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3377 return RC;
3378
3379 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003380 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003381 if (!M)
3382 return nullptr;
3383 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3384 if (!PDecl)
3385 return nullptr;
3386
3387 return Ctx.getRawCommentForAnyRedecl(PDecl);
3388}
3389
3390const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3391 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003392 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003393 if (!M || !M->isPropertyAccessor())
3394 return nullptr;
3395
3396 // Provide code completion comment for self.GetterName where
3397 // GetterName is the getter method for a property with name
3398 // different from the property name (declared via a property
3399 // getter attribute.
3400 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3401 if (!PDecl)
3402 return nullptr;
3403 if (PDecl->getGetterName() == M->getSelector() &&
3404 PDecl->getIdentifier() != M->getIdentifier()) {
3405 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3406 return RC;
3407 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3408 return RC;
3409 }
3410 return nullptr;
3411}
3412
3413const RawComment *clang::getParameterComment(
3414 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003415 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003416 auto FDecl = Result.getFunction();
3417 if (!FDecl)
3418 return nullptr;
3419 if (ArgIndex < FDecl->getNumParams())
3420 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3421 return nullptr;
3422}
3423
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003424/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003425/// string.
3426static void AddOverloadParameterChunks(ASTContext &Context,
3427 const PrintingPolicy &Policy,
3428 const FunctionDecl *Function,
3429 const FunctionProtoType *Prototype,
3430 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003431 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003432 bool InOptional = false) {
3433 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003434 unsigned NumParams =
3435 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003436
3437 for (unsigned P = Start; P != NumParams; ++P) {
3438 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3439 // When we see an optional default argument, put that argument and
3440 // the remaining default arguments into a new, optional string.
3441 CodeCompletionBuilder Opt(Result.getAllocator(),
3442 Result.getCodeCompletionTUInfo());
3443 if (!FirstParameter)
3444 Opt.AddChunk(CodeCompletionString::CK_Comma);
3445 // Optional sections are nested.
3446 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3447 CurrentArg, P, /*InOptional=*/true);
3448 Result.AddOptionalChunk(Opt.TakeString());
3449 return;
3450 }
3451
3452 if (FirstParameter)
3453 FirstParameter = false;
3454 else
3455 Result.AddChunk(CodeCompletionString::CK_Comma);
3456
3457 InOptional = false;
3458
3459 // Format the placeholder string.
3460 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003461 if (Function) {
3462 const ParmVarDecl *Param = Function->getParamDecl(P);
3463 Placeholder = FormatFunctionParameter(Policy, Param);
3464 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003465 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3466 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003467 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003468 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003469 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003470
3471 if (P == CurrentArg)
3472 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003473 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003474 else
3475 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3476 }
3477
3478 if (Prototype && Prototype->isVariadic()) {
3479 CodeCompletionBuilder Opt(Result.getAllocator(),
3480 Result.getCodeCompletionTUInfo());
3481 if (!FirstParameter)
3482 Opt.AddChunk(CodeCompletionString::CK_Comma);
3483
3484 if (CurrentArg < NumParams)
3485 Opt.AddPlaceholderChunk("...");
3486 else
3487 Opt.AddCurrentParameterChunk("...");
3488
3489 Result.AddOptionalChunk(Opt.TakeString());
3490 }
3491}
3492
Douglas Gregorf0f51982009-09-23 00:34:09 +00003493CodeCompletionString *
3494CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003495 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3496 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003497 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003498
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003499 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003500 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3501 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003502 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003503 const FunctionProtoType *Proto =
3504 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003505 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003506 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003507 // highlighted ellipsis.
3508 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003509 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003510 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003511 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3512 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3513 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003514 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003515 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003516
3517 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003518 if (IncludeBriefComments) {
3519 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003520 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003521 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003522 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003523 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003524 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003525 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003526 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003527 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003528 }
Alp Toker314cc812014-01-25 16:55:45 +00003529
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003530 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003531 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3532 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003533 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003534
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003535 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003536}
3537
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003538unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003539 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003540 bool PreferredTypeIsPointer) {
3541 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003542
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003543 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003544 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003545 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003546 Priority = CCP_Constant;
3547 if (PreferredTypeIsPointer)
3548 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003549 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003550 // Treat "YES", "NO", "true", and "false" as constants.
3551 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3552 MacroName.equals("true") || MacroName.equals("false"))
3553 Priority = CCP_Constant;
3554 // Treat "bool" as a type.
3555 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003556 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003557
Douglas Gregor6e240332010-08-16 16:18:59 +00003558 return Priority;
3559}
3560
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003561CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003562 if (!D)
3563 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003564
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003565 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003566 case Decl::Enum:
3567 return CXCursor_EnumDecl;
3568 case Decl::EnumConstant:
3569 return CXCursor_EnumConstantDecl;
3570 case Decl::Field:
3571 return CXCursor_FieldDecl;
3572 case Decl::Function:
3573 return CXCursor_FunctionDecl;
3574 case Decl::ObjCCategory:
3575 return CXCursor_ObjCCategoryDecl;
3576 case Decl::ObjCCategoryImpl:
3577 return CXCursor_ObjCCategoryImplDecl;
3578 case Decl::ObjCImplementation:
3579 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003580
Fangrui Song050229d2018-11-24 00:14:31 +00003581 case Decl::ObjCInterface:
3582 return CXCursor_ObjCInterfaceDecl;
3583 case Decl::ObjCIvar:
3584 return CXCursor_ObjCIvarDecl;
3585 case Decl::ObjCMethod:
3586 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3587 ? CXCursor_ObjCInstanceMethodDecl
3588 : CXCursor_ObjCClassMethodDecl;
3589 case Decl::CXXMethod:
3590 return CXCursor_CXXMethod;
3591 case Decl::CXXConstructor:
3592 return CXCursor_Constructor;
3593 case Decl::CXXDestructor:
3594 return CXCursor_Destructor;
3595 case Decl::CXXConversion:
3596 return CXCursor_ConversionFunction;
3597 case Decl::ObjCProperty:
3598 return CXCursor_ObjCPropertyDecl;
3599 case Decl::ObjCProtocol:
3600 return CXCursor_ObjCProtocolDecl;
3601 case Decl::ParmVar:
3602 return CXCursor_ParmDecl;
3603 case Decl::Typedef:
3604 return CXCursor_TypedefDecl;
3605 case Decl::TypeAlias:
3606 return CXCursor_TypeAliasDecl;
3607 case Decl::TypeAliasTemplate:
3608 return CXCursor_TypeAliasTemplateDecl;
3609 case Decl::Var:
3610 return CXCursor_VarDecl;
3611 case Decl::Namespace:
3612 return CXCursor_Namespace;
3613 case Decl::NamespaceAlias:
3614 return CXCursor_NamespaceAlias;
3615 case Decl::TemplateTypeParm:
3616 return CXCursor_TemplateTypeParameter;
3617 case Decl::NonTypeTemplateParm:
3618 return CXCursor_NonTypeTemplateParameter;
3619 case Decl::TemplateTemplateParm:
3620 return CXCursor_TemplateTemplateParameter;
3621 case Decl::FunctionTemplate:
3622 return CXCursor_FunctionTemplate;
3623 case Decl::ClassTemplate:
3624 return CXCursor_ClassTemplate;
3625 case Decl::AccessSpec:
3626 return CXCursor_CXXAccessSpecifier;
3627 case Decl::ClassTemplatePartialSpecialization:
3628 return CXCursor_ClassTemplatePartialSpecialization;
3629 case Decl::UsingDirective:
3630 return CXCursor_UsingDirective;
3631 case Decl::StaticAssert:
3632 return CXCursor_StaticAssert;
3633 case Decl::Friend:
3634 return CXCursor_FriendDecl;
3635 case Decl::TranslationUnit:
3636 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003637
Fangrui Song050229d2018-11-24 00:14:31 +00003638 case Decl::Using:
3639 case Decl::UnresolvedUsingValue:
3640 case Decl::UnresolvedUsingTypename:
3641 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003642
Fangrui Song050229d2018-11-24 00:14:31 +00003643 case Decl::ObjCPropertyImpl:
3644 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3645 case ObjCPropertyImplDecl::Dynamic:
3646 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003647
Fangrui Song050229d2018-11-24 00:14:31 +00003648 case ObjCPropertyImplDecl::Synthesize:
3649 return CXCursor_ObjCSynthesizeDecl;
3650 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003651 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003652
3653 case Decl::Import:
3654 return CXCursor_ModuleImportDecl;
3655
3656 case Decl::ObjCTypeParam:
3657 return CXCursor_TemplateTypeParameter;
3658
3659 default:
3660 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3661 switch (TD->getTagKind()) {
3662 case TTK_Interface: // fall through
3663 case TTK_Struct:
3664 return CXCursor_StructDecl;
3665 case TTK_Class:
3666 return CXCursor_ClassDecl;
3667 case TTK_Union:
3668 return CXCursor_UnionDecl;
3669 case TTK_Enum:
3670 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003671 }
Fangrui Song050229d2018-11-24 00:14:31 +00003672 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003673 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003674
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003675 return CXCursor_UnexposedDecl;
3676}
3677
Douglas Gregor55b037b2010-07-08 20:55:51 +00003678static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003679 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003680 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003681 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003682
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003683 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003684
Eric Liu88de9f62018-09-19 09:34:55 +00003685 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3686 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003687 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003688 auto MD = PP.getMacroDefinition(M->first);
3689 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003690 MacroInfo *MI = MD.getMacroInfo();
3691 if (MI && MI->isUsedForHeaderGuard())
3692 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003693
Eric Liud485df12018-09-05 14:59:17 +00003694 Results.AddResult(
3695 Result(M->first, MI,
3696 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3697 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003698 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003699 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003700
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003701 Results.ExitScope();
3702}
3703
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003704static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003705 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003706 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003707
Douglas Gregorce0e8562010-08-23 21:54:33 +00003708 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003709
Douglas Gregorce0e8562010-08-23 21:54:33 +00003710 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3711 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003712 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003713 Results.AddResult(Result("__func__", CCP_Constant));
3714 Results.ExitScope();
3715}
3716
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003717static void HandleCodeCompleteResults(Sema *S,
3718 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003719 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003720 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003721 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003722 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003723 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003724}
3725
Ilya Biryukov41109672018-12-13 15:36:32 +00003726static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003727mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003728 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003729 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003730 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003731
John McCallfaf5fb42010-08-26 23:41:50 +00003732 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003733 return CodeCompletionContext::CCC_ClassStructUnion;
3734
John McCallfaf5fb42010-08-26 23:41:50 +00003735 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003736 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003737
John McCallfaf5fb42010-08-26 23:41:50 +00003738 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003739 return CodeCompletionContext::CCC_ObjCImplementation;
3740
John McCallfaf5fb42010-08-26 23:41:50 +00003741 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003742 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003743
John McCallfaf5fb42010-08-26 23:41:50 +00003744 case Sema::PCC_Template:
3745 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003746 if (S.CurContext->isFileContext())
3747 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003748 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003749 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003750 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003751
John McCallfaf5fb42010-08-26 23:41:50 +00003752 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003753 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003754
John McCallfaf5fb42010-08-26 23:41:50 +00003755 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003756 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003757 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003758 return CodeCompletionContext::CCC_ParenthesizedExpression;
3759 else
3760 return CodeCompletionContext::CCC_Expression;
3761
3762 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003763 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003764 case Sema::PCC_Condition:
3765 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3766 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003767
John McCallfaf5fb42010-08-26 23:41:50 +00003768 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003769 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003770
John McCallfaf5fb42010-08-26 23:41:50 +00003771 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003772 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003773
3774 case Sema::PCC_ParenthesizedExpression:
3775 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003776
Douglas Gregor80039242011-02-15 20:33:25 +00003777 case Sema::PCC_LocalDeclarationSpecifiers:
3778 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003779 }
David Blaikie8a40f702012-01-17 06:56:22 +00003780
3781 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003782}
3783
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003784/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003785/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003786/// overridden function as well as adding new functionality.
3787///
3788/// \param S The semantic analysis object for which we are generating results.
3789///
3790/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003791/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003792static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3793 ResultBuilder &Results) {
3794 // Look through blocks.
3795 DeclContext *CurContext = S.CurContext;
3796 while (isa<BlockDecl>(CurContext))
3797 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003798
Douglas Gregorac322ec2010-08-27 21:18:54 +00003799 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3800 if (!Method || !Method->isVirtual())
3801 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003802
3803 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003804 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003805 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003806 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003807 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003808
Douglas Gregor75acd922011-09-27 23:30:47 +00003809 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003810 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003811 CodeCompletionBuilder Builder(Results.getAllocator(),
3812 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003813 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3814 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003815
Douglas Gregorac322ec2010-08-27 21:18:54 +00003816 // If we need a nested-name-specifier, add one now.
3817 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003818 NestedNameSpecifier *NNS = getRequiredQualification(
3819 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003820 if (NNS) {
3821 std::string Str;
3822 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003823 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003824 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003825 }
3826 } else if (!InContext->Equals(Overridden->getDeclContext()))
3827 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003828
Fangrui Song050229d2018-11-24 00:14:31 +00003829 Builder.AddTypedTextChunk(
3830 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003831 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003832 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003833 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003834 if (FirstParam)
3835 FirstParam = false;
3836 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003837 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003838
Aaron Ballman43b68be2014-03-07 17:50:17 +00003839 Builder.AddPlaceholderChunk(
3840 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003841 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003842 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003843 Results.AddResult(CodeCompletionResult(
3844 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3845 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003846 Results.Ignore(Overridden);
3847 }
3848}
3849
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003850void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003851 ModuleIdPath Path) {
3852 typedef CodeCompletionResult Result;
3853 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003854 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003855 CodeCompletionContext::CCC_Other);
3856 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003857
Douglas Gregor07f43572012-01-29 18:15:03 +00003858 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003859 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003860 typedef CodeCompletionResult Result;
3861 if (Path.empty()) {
3862 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003863 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003864 PP.getHeaderSearchInfo().collectAllModules(Modules);
3865 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3866 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003867 Builder.getAllocator().CopyString(Modules[I]->Name));
3868 Results.AddResult(Result(
3869 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3870 Modules[I]->isAvailable() ? CXAvailability_Available
3871 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003872 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003873 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003874 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003875 Module *Mod =
3876 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3877 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003878 // Enumerate submodules.
3879 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003880 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003881 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003882 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003883
Douglas Gregor07f43572012-01-29 18:15:03 +00003884 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003885 Builder.getAllocator().CopyString((*Sub)->Name));
3886 Results.AddResult(Result(
3887 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3888 (*Sub)->isAvailable() ? CXAvailability_Available
3889 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003890 }
3891 }
3892 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003893 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003894 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003895 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003896}
3897
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003898void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003899 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003900 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003901 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003902 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003903 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003904
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003905 // Determine how to filter results, e.g., so that the names of
3906 // values (functions, enumerators, function templates, etc.) are
3907 // only allowed where we can have an expression.
3908 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003909 case PCC_Namespace:
3910 case PCC_Class:
3911 case PCC_ObjCInterface:
3912 case PCC_ObjCImplementation:
3913 case PCC_ObjCInstanceVariableList:
3914 case PCC_Template:
3915 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003916 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003917 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003918 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3919 break;
3920
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003921 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003922 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003923 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003924 case PCC_ForInit:
3925 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003926 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003927 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3928 else
3929 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003930
David Blaikiebbafb8a2012-03-11 07:00:24 +00003931 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003932 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003933 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003934
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003935 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003936 // Unfiltered
3937 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003938 }
3939
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003940 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003941 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00003942 auto ThisType = getCurrentThisType();
3943 if (!ThisType.isNull())
3944 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003945
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003946 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003947 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003948 CodeCompleter->includeGlobals(),
3949 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003950
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003951 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003952 Results.ExitScope();
3953
Douglas Gregorce0e8562010-08-23 21:54:33 +00003954 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003955 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003956 case PCC_Expression:
3957 case PCC_Statement:
3958 case PCC_RecoveryInFunction:
3959 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003960 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003961 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003962
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003963 case PCC_Namespace:
3964 case PCC_Class:
3965 case PCC_ObjCInterface:
3966 case PCC_ObjCImplementation:
3967 case PCC_ObjCInstanceVariableList:
3968 case PCC_Template:
3969 case PCC_MemberTemplate:
3970 case PCC_ForInit:
3971 case PCC_Condition:
3972 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003973 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003974 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003975 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003976
Douglas Gregor9eb77012009-11-07 00:00:49 +00003977 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003978 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003979
Douglas Gregor50832e02010-09-20 22:39:41 +00003980 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003981 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003982}
3983
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003984static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003985 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003986 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00003987 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003988 ResultBuilder &Results);
3989
3990void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3991 bool AllowNonIdentifiers,
3992 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003993 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00003994 ResultBuilder Results(
3995 *this, CodeCompleter->getAllocator(),
3996 CodeCompleter->getCodeCompletionTUInfo(),
3997 AllowNestedNameSpecifiers
3998 // FIXME: Try to separate codepath leading here to deduce whether we
3999 // need an existing symbol or a new one.
4000 ? CodeCompletionContext::CCC_SymbolOrNewName
4001 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004002 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004003
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004004 // Type qualifiers can come after names.
4005 Results.AddResult(Result("const"));
4006 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004007 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004008 Results.AddResult(Result("restrict"));
4009
David Blaikiebbafb8a2012-03-11 07:00:24 +00004010 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004011 if (getLangOpts().CPlusPlus11 &&
4012 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4013 DS.getTypeSpecType() == DeclSpec::TST_struct))
4014 Results.AddResult("final");
4015
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004016 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004017 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004018 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004019
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004020 // Add nested-name-specifiers.
4021 if (AllowNestedNameSpecifiers) {
4022 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004023 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004024 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4025 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004026 CodeCompleter->includeGlobals(),
4027 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004028 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004029 }
4030 }
4031 Results.ExitScope();
4032
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004033 // If we're in a context where we might have an expression (rather than a
4034 // declaration), and what we've seen so far is an Objective-C type that could
4035 // be a receiver of a class message, this may be a class message send with
4036 // the initial opening bracket '[' missing. Add appropriate completions.
4037 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004038 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004039 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004040 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4041 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004042 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004043 (S->getFlags() & Scope::DeclScope) != 0 &&
4044 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004045 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4046 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004047 ParsedType T = DS.getRepAsType();
4048 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004049 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004050 }
4051
Douglas Gregor56ccce02010-08-24 04:59:56 +00004052 // Note that we intentionally suppress macro results here, since we do not
4053 // encourage using macros to produce the names of entities.
4054
Fangrui Song050229d2018-11-24 00:14:31 +00004055 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004056 Results.data(), Results.size());
4057}
4058
Douglas Gregor68762e72010-08-23 21:17:50 +00004059struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004060 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4061 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004062 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004063 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004064
Douglas Gregor68762e72010-08-23 21:17:50 +00004065 QualType PreferredType;
4066 bool IntegralConstantExpression;
4067 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004068 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004069 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004070};
4071
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004072/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004073/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004074void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004075 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004076 ResultBuilder Results(
4077 *this, CodeCompleter->getAllocator(),
4078 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004079 CodeCompletionContext(
4080 Data.IsParenthesized
4081 ? CodeCompletionContext::CCC_ParenthesizedExpression
4082 : CodeCompletionContext::CCC_Expression,
4083 Data.PreferredType));
4084 auto PCC =
4085 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004086 if (Data.ObjCCollection)
4087 Results.setFilter(&ResultBuilder::IsObjCCollection);
4088 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004089 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004090 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004091 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4092 else
4093 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004094
4095 if (!Data.PreferredType.isNull())
4096 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004097
Douglas Gregor68762e72010-08-23 21:17:50 +00004098 // Ignore any declarations that we were told that we don't care about.
4099 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4100 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004101
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004102 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004103 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004104 CodeCompleter->includeGlobals(),
4105 CodeCompleter->loadExternal());
4106
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004107 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004108 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004109 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004110
Douglas Gregor55b037b2010-07-08 20:55:51 +00004111 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00004112 if (!Data.PreferredType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00004113 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4114 Data.PreferredType->isMemberPointerType() ||
4115 Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004116
Fangrui Song050229d2018-11-24 00:14:31 +00004117 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004118 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004119 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004120
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004121 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004122 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4123 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00004124 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4125 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004126}
4127
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004128void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4129 bool IsParenthesized) {
4130 return CodeCompleteExpression(
4131 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004132}
4133
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004134void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4135 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004136 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004137 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004138 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004139 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004140}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004141
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004142/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004143/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004144typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004145
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004146/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004147static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4148 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4149 if (Interface->hasDefinition())
4150 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004151
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004152 return Interface;
4153 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004154
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004155 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4156 if (Protocol->hasDefinition())
4157 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004158
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004159 return Protocol;
4160 }
4161 return Container;
4162}
4163
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004164/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004165/// declaration \p BD.
4166static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4167 CodeCompletionBuilder &Builder,
4168 const NamedDecl *BD,
4169 const FunctionTypeLoc &BlockLoc,
4170 const FunctionProtoTypeLoc &BlockProtoLoc) {
4171 Builder.AddResultTypeChunk(
4172 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4173 Policy, Builder.getAllocator()));
4174
4175 AddTypedNameChunk(Context, Policy, BD, Builder);
4176 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4177
4178 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4179 Builder.AddPlaceholderChunk("...");
4180 } else {
4181 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4182 if (I)
4183 Builder.AddChunk(CodeCompletionString::CK_Comma);
4184
4185 // Format the placeholder string.
4186 std::string PlaceholderStr =
4187 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4188
4189 if (I == N - 1 && BlockProtoLoc &&
4190 BlockProtoLoc.getTypePtr()->isVariadic())
4191 PlaceholderStr += ", ...";
4192
4193 // Add the placeholder string.
4194 Builder.AddPlaceholderChunk(
4195 Builder.getAllocator().CopyString(PlaceholderStr));
4196 }
4197 }
4198
4199 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4200}
4201
Fangrui Song050229d2018-11-24 00:14:31 +00004202static void
4203AddObjCProperties(const CodeCompletionContext &CCContext,
4204 ObjCContainerDecl *Container, bool AllowCategories,
4205 bool AllowNullaryMethods, DeclContext *CurContext,
4206 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4207 bool IsBaseExprStatement = false,
4208 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004209 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004210
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004211 // Retrieve the definition.
4212 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004213
Douglas Gregor9291bad2009-11-18 01:29:26 +00004214 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004215 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004216 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004217 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004218
Alex Lorenzbaef8022016-11-09 13:43:18 +00004219 // FIXME: Provide block invocation completion for non-statement
4220 // expressions.
4221 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4222 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004223 Result R = Result(P, Results.getBasePriority(P), nullptr);
4224 if (!InOriginalClass)
4225 setInBaseClass(R);
4226 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004227 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004228 }
4229
4230 // Block setter and invocation completion is provided only when we are able
4231 // to find the FunctionProtoTypeLoc with parameter names for the block.
4232 FunctionTypeLoc BlockLoc;
4233 FunctionProtoTypeLoc BlockProtoLoc;
4234 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4235 BlockProtoLoc);
4236 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004237 Result R = Result(P, Results.getBasePriority(P), nullptr);
4238 if (!InOriginalClass)
4239 setInBaseClass(R);
4240 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004241 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004242 }
4243
4244 // The default completion result for block properties should be the block
4245 // invocation completion when the base expression is a statement.
4246 CodeCompletionBuilder Builder(Results.getAllocator(),
4247 Results.getCodeCompletionTUInfo());
4248 AddObjCBlockCall(Container->getASTContext(),
4249 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4250 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004251 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4252 if (!InOriginalClass)
4253 setInBaseClass(R);
4254 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004255
4256 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004257 // statement and the block property is mutable.
4258 if (!P->isReadOnly()) {
4259 CodeCompletionBuilder Builder(Results.getAllocator(),
4260 Results.getCodeCompletionTUInfo());
4261 AddResultTypeChunk(Container->getASTContext(),
4262 getCompletionPrintingPolicy(Results.getSema()), P,
4263 CCContext.getBaseType(), Builder);
4264 Builder.AddTypedTextChunk(
4265 Results.getAllocator().CopyString(P->getName()));
4266 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004267
Alex Lorenzbaef8022016-11-09 13:43:18 +00004268 std::string PlaceholderStr = formatBlockPlaceholder(
4269 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4270 BlockProtoLoc, /*SuppressBlockName=*/true);
4271 // Add the placeholder string.
4272 Builder.AddPlaceholderChunk(
4273 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004274
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004275 // When completing blocks properties that return void the default
4276 // property completion result should show up before the setter,
4277 // otherwise the setter completion should show up before the default
4278 // property completion, as we normally want to use the result of the
4279 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004280 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004281 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004282 Results.getBasePriority(P) +
4283 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4284 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004285 : -CCD_BlockPropertySetter));
4286 if (!InOriginalClass)
4287 setInBaseClass(R);
4288 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004289 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004290 };
4291
4292 if (IsClassProperty) {
4293 for (const auto *P : Container->class_properties())
4294 AddProperty(P);
4295 } else {
4296 for (const auto *P : Container->instance_properties())
4297 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004298 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004299
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004300 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004301 if (AllowNullaryMethods) {
4302 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004303 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004304 // Adds a method result
4305 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4306 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4307 if (!Name)
4308 return;
4309 if (!AddedProperties.insert(Name).second)
4310 return;
4311 CodeCompletionBuilder Builder(Results.getAllocator(),
4312 Results.getCodeCompletionTUInfo());
4313 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4314 Builder.AddTypedTextChunk(
4315 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004316 Result R = Result(Builder.TakeString(), M,
4317 CCP_MemberDeclaration + CCD_MethodAsProperty);
4318 if (!InOriginalClass)
4319 setInBaseClass(R);
4320 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004321 };
4322
4323 if (IsClassProperty) {
4324 for (const auto *M : Container->methods()) {
4325 // Gather the class method that can be used as implicit property
4326 // getters. Methods with arguments or methods that return void aren't
4327 // added to the results as they can't be used as a getter.
4328 if (!M->getSelector().isUnarySelector() ||
4329 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4330 continue;
4331 AddMethod(M);
4332 }
4333 } else {
4334 for (auto *M : Container->methods()) {
4335 if (M->getSelector().isUnarySelector())
4336 AddMethod(M);
4337 }
Douglas Gregor95147142011-05-05 15:50:42 +00004338 }
4339 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004340
Douglas Gregor9291bad2009-11-18 01:29:26 +00004341 // Add properties in referenced protocols.
4342 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004343 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004344 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004345 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004346 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004347 /*InOriginalClass*/ false);
4348 } else if (ObjCInterfaceDecl *IFace =
4349 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004350 if (AllowCategories) {
4351 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004352 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004353 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004354 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004355 IsBaseExprStatement, IsClassProperty,
4356 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004357 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004358
Douglas Gregor9291bad2009-11-18 01:29:26 +00004359 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004360 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004361 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004362 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004363 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004364 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004365
Douglas Gregor9291bad2009-11-18 01:29:26 +00004366 // Look in the superclass.
4367 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004368 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004369 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004370 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004371 /*InOriginalClass*/ false);
4372 } else if (const auto *Category =
4373 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004374 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004375 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004376 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004377 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004378 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004379 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004380 }
4381}
4382
Fangrui Song050229d2018-11-24 00:14:31 +00004383static void
4384AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
4385 Scope *S, QualType BaseType, RecordDecl *RD,
4386 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004387 // Indicate that we are performing a member access, and the cv-qualifiers
4388 // for the base object type.
4389 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4390
4391 // Access to a C/C++ class, struct, or union.
4392 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004393 std::vector<FixItHint> FixIts;
4394 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004395 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004396 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004397 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004398 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004399 /*IncludeDependentBases=*/true,
4400 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004401
4402 if (SemaRef.getLangOpts().CPlusPlus) {
4403 if (!Results.empty()) {
4404 // The "template" keyword can follow "->" or "." in the grammar.
4405 // However, we only want to suggest the template keyword if something
4406 // is dependent.
4407 bool IsDependent = BaseType->isDependentType();
4408 if (!IsDependent) {
4409 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4410 if (DeclContext *Ctx = DepScope->getEntity()) {
4411 IsDependent = Ctx->isDependentContext();
4412 break;
4413 }
4414 }
4415
4416 if (IsDependent)
4417 Results.AddResult(CodeCompletionResult("template"));
4418 }
4419 }
4420}
4421
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004422void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004423 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004424 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004425 bool IsBaseExprStatement,
4426 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004427 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004428 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004429
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004430 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4431 if (ConvertedBase.isInvalid())
4432 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004433 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4434
4435 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004436
4437 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004438 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004439 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004440 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004441
Douglas Gregor21325842011-07-07 16:03:39 +00004442 if (IsArrow) {
4443 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004444 } else {
4445 if (ConvertedBaseType->isObjCObjectPointerType() ||
4446 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004447 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004448 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004449 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4450 }
4451 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004452
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004453 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004454 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004455 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004456 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004457 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004458
Fangrui Song050229d2018-11-24 00:14:31 +00004459 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4460 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004461 if (!Base)
4462 return false;
4463
4464 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4465 if (ConvertedBase.isInvalid())
4466 return false;
4467 Base = ConvertedBase.get();
4468
4469 QualType BaseType = Base->getType();
4470
4471 if (IsArrow) {
4472 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4473 BaseType = Ptr->getPointeeType();
4474 else if (BaseType->isObjCObjectPointerType())
4475 /*Do nothing*/;
4476 else
4477 return false;
4478 }
4479
4480 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4481 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4482 Record->getDecl(),
4483 std::move(AccessOpFixIt));
4484 } else if (const auto *TST =
4485 BaseType->getAs<TemplateSpecializationType>()) {
4486 TemplateName TN = TST->getTemplateName();
4487 if (const auto *TD =
4488 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4489 CXXRecordDecl *RD = TD->getTemplatedDecl();
4490 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4491 std::move(AccessOpFixIt));
4492 }
4493 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4494 if (auto *RD = ICNT->getDecl())
4495 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4496 std::move(AccessOpFixIt));
4497 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4498 // Objective-C property reference.
4499 AddedPropertiesSet AddedProperties;
4500
4501 if (const ObjCObjectPointerType *ObjCPtr =
4502 BaseType->getAsObjCInterfacePointerType()) {
4503 // Add property results based on our interface.
4504 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4505 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4506 /*AllowNullaryMethods=*/true, CurContext,
4507 AddedProperties, Results, IsBaseExprStatement);
4508 }
4509
4510 // Add properties from the protocols in a qualified interface.
4511 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4512 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4513 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004514 IsBaseExprStatement, /*IsClassProperty*/ false,
4515 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004516 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4517 (!IsArrow && BaseType->isObjCObjectType())) {
4518 // Objective-C instance variable access.
4519 ObjCInterfaceDecl *Class = nullptr;
4520 if (const ObjCObjectPointerType *ObjCPtr =
4521 BaseType->getAs<ObjCObjectPointerType>())
4522 Class = ObjCPtr->getInterfaceDecl();
4523 else
4524 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4525
4526 // Add all ivars from this class and its superclasses.
4527 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004528 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004529 Results.setFilter(&ResultBuilder::IsObjCIvar);
4530 LookupVisibleDecls(
4531 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4532 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4533 }
4534 }
4535
4536 // FIXME: How do we cope with isa?
4537 return true;
4538 };
4539
Douglas Gregor9291bad2009-11-18 01:29:26 +00004540 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004541
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004542 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4543 if (CodeCompleter->includeFixIts()) {
4544 const CharSourceRange OpRange =
4545 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4546 CompletionSucceded |= DoCompletion(
4547 OtherOpBase, !IsArrow,
4548 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004549 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004550
Douglas Gregor9291bad2009-11-18 01:29:26 +00004551 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004552
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004553 if (!CompletionSucceded)
4554 return;
4555
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004556 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004557 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4558 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004559}
4560
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004561void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4562 IdentifierInfo &ClassName,
4563 SourceLocation ClassNameLoc,
4564 bool IsBaseExprStatement) {
4565 IdentifierInfo *ClassNamePtr = &ClassName;
4566 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4567 if (!IFace)
4568 return;
4569 CodeCompletionContext CCContext(
4570 CodeCompletionContext::CCC_ObjCPropertyAccess);
4571 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4572 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4573 &ResultBuilder::IsMember);
4574 Results.EnterNewScope();
4575 AddedPropertiesSet AddedProperties;
4576 AddObjCProperties(CCContext, IFace, true,
4577 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4578 Results, IsBaseExprStatement,
4579 /*IsClassProperty=*/true);
4580 Results.ExitScope();
4581 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4582 Results.data(), Results.size());
4583}
4584
Faisal Vali090da2d2018-01-01 18:23:28 +00004585void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004586 if (!CodeCompleter)
4587 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004588
4589 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004590 enum CodeCompletionContext::Kind ContextKind =
4591 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004592 switch ((DeclSpec::TST)TagSpec) {
4593 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004594 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004595 ContextKind = CodeCompletionContext::CCC_EnumTag;
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_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004599 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004600 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004601 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004602
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004603 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004604 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004605 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004606 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004607 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004608 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004609
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004610 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004611 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004612 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004613
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004614 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4615 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004616 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004617
4618 // First pass: look for tags.
4619 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004620 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004621 CodeCompleter->includeGlobals(),
4622 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004623
Douglas Gregor39982192010-08-15 06:18:01 +00004624 if (CodeCompleter->includeGlobals()) {
4625 // Second pass: look for nested name specifiers.
4626 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004627 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4628 CodeCompleter->includeGlobals(),
4629 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004630 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004631
Douglas Gregor0ac41382010-09-23 23:01:17 +00004632 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004633 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004634}
4635
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004636static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4637 const LangOptions &LangOpts) {
4638 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4639 Results.AddResult("const");
4640 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4641 Results.AddResult("volatile");
4642 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4643 Results.AddResult("restrict");
4644 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4645 Results.AddResult("_Atomic");
4646 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4647 Results.AddResult("__unaligned");
4648}
4649
Douglas Gregor28c78432010-08-27 17:35:51 +00004650void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004651 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004652 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004653 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004654 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004655 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004656 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004657 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004658 Results.data(), Results.size());
4659}
4660
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004661void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4662 const VirtSpecifiers *VS) {
4663 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4664 CodeCompleter->getCodeCompletionTUInfo(),
4665 CodeCompletionContext::CCC_TypeQualifiers);
4666 Results.EnterNewScope();
4667 AddTypeQualifierResults(DS, Results, LangOpts);
4668 if (LangOpts.CPlusPlus11) {
4669 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004670 if (D.getContext() == DeclaratorContext::MemberContext &&
4671 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004672 if (!VS || !VS->isFinalSpecified())
4673 Results.AddResult("final");
4674 if (!VS || !VS->isOverrideSpecified())
4675 Results.AddResult("override");
4676 }
4677 }
4678 Results.ExitScope();
4679 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4680 Results.data(), Results.size());
4681}
4682
Benjamin Kramer72dae622016-02-18 15:30:24 +00004683void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4684 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4685}
4686
Douglas Gregord328d572009-09-21 18:10:23 +00004687void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004688 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004689 return;
John McCall5939b162011-08-06 07:30:58 +00004690
Richard Smithef6c43d2018-07-26 18:41:30 +00004691 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004692 // Condition expression might be invalid, do not continue in this case.
4693 if (!Switch->getCond())
4694 return;
John McCall5939b162011-08-06 07:30:58 +00004695 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4696 if (!type->isEnumeralType()) {
4697 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004698 Data.IntegralConstantExpression = true;
4699 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004700 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004701 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004702
Douglas Gregord328d572009-09-21 18:10:23 +00004703 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004704 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004705 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004706 if (EnumDecl *Def = Enum->getDefinition())
4707 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004708
Douglas Gregord328d572009-09-21 18:10:23 +00004709 // Determine which enumerators we have already seen in the switch statement.
4710 // FIXME: Ideally, we would also be able to look *past* the code-completion
4711 // token, in case we are code-completing in the middle of the switch and not
4712 // at the end. However, we aren't able to do so at the moment.
4713 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004714 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004715 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004716 SC = SC->getNextSwitchCase()) {
4717 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4718 if (!Case)
4719 continue;
4720
4721 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004722 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4723 if (auto *Enumerator =
4724 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004725 // We look into the AST of the case statement to determine which
4726 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004727 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004728 // values of each enumerator. However, value-based approach would not
4729 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004730 // template are type- and value-dependent.
4731 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004732
Douglas Gregorf2510672009-09-21 19:57:38 +00004733 // If this is a qualified-id, keep track of the nested-name-specifier
4734 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004735 //
4736 // switch (TagD.getKind()) {
4737 // case TagDecl::TK_enum:
4738 // break;
4739 // case XXX
4740 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004741 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004742 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4743 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004744 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004745 }
4746 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004747
David Blaikiebbafb8a2012-03-11 07:00:24 +00004748 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004749 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004750 // qualify the names of the enumerators that we suggest, because they
4751 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004752 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004753 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004754
Douglas Gregord328d572009-09-21 18:10:23 +00004755 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004756 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004757 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004758 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004759 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004760 for (auto *E : Enum->enumerators()) {
4761 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004762 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004763
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004764 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004765 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004766 }
4767 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004768
Douglas Gregor21325842011-07-07 16:03:39 +00004769 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004770 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004771 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004772 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4773 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004774}
4775
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004776static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004777 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004778 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004779
4780 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004781 if (!Args[I])
4782 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004783
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004784 return false;
4785}
4786
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004787typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4788
Fangrui Song050229d2018-11-24 00:14:31 +00004789static void mergeCandidatesWithResults(
4790 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
4791 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004792 if (!CandidateSet.empty()) {
4793 // Sort the overload candidate set by placing the best overloads first.
4794 std::stable_sort(
4795 CandidateSet.begin(), CandidateSet.end(),
4796 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004797 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4798 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004799 });
4800
4801 // Add the remaining viable overload candidates as code-completion results.
Fangrui Song050229d2018-11-24 00:14:31 +00004802 for (OverloadCandidate &Candidate : CandidateSet) {
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004803 if (Candidate.Function && Candidate.Function->isDeleted())
4804 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004805 if (Candidate.Viable)
4806 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004807 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004808 }
4809}
4810
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004811/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004812/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004813static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00004814 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004815
4816 // Given the overloads 'Candidates' for a function call matching all arguments
4817 // up to N, return the type of the Nth parameter if it is the same for all
4818 // overload candidates.
4819 QualType ParamType;
4820 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00004821 if (const auto *FType = Candidate.getFunctionType())
4822 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004823 if (N < Proto->getNumParams()) {
4824 if (ParamType.isNull())
4825 ParamType = Proto->getParamType(N);
4826 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00004827 ParamType.getNonReferenceType(),
4828 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004829 // Otherwise return a default-constructed QualType.
4830 return QualType();
4831 }
4832 }
4833
4834 return ParamType;
4835}
4836
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004837static QualType
4838ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4839 MutableArrayRef<ResultCandidate> Candidates,
4840 unsigned CurrentArg, SourceLocation OpenParLoc) {
4841 if (Candidates.empty())
4842 return QualType();
4843 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4844 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4845 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004846}
4847
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004848QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4849 ArrayRef<Expr *> Args,
4850 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004851 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004852 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004853
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004854 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004855 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004856 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4857 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004858 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004859 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004860
John McCall57500772009-12-16 12:17:52 +00004861 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004862 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004863 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004864
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004865 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004866
John McCall57500772009-12-16 12:17:52 +00004867 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004868 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004869 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004870 /*PartialOverloading=*/true);
4871 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4872 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4873 if (UME->hasExplicitTemplateArgs()) {
4874 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4875 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004876 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004877
4878 // Add the base as first argument (use a nullptr if the base is implicit).
4879 SmallVector<Expr *, 12> ArgExprs(
4880 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004881 ArgExprs.append(Args.begin(), Args.end());
4882 UnresolvedSet<8> Decls;
4883 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004884 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004885 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4886 /*SuppressUsedConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00004887 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004888 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004889 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004890 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004891 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00004892 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004893 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004894 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004895 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004896 !FD->getType()->getAs<FunctionProtoType>())
4897 Results.push_back(ResultCandidate(FD));
4898 else
4899 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4900 Args, CandidateSet,
4901 /*SuppressUsedConversions=*/false,
4902 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004903
4904 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4905 // If expression's type is CXXRecordDecl, it may overload the function
4906 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004907 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004908 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00004909 DeclarationName OpName =
4910 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004911 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4912 LookupQualifiedName(R, DC);
4913 R.suppressDiagnostics();
4914 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4915 ArgExprs.append(Args.begin(), Args.end());
4916 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4917 /*ExplicitArgs=*/nullptr,
4918 /*SuppressUsedConversions=*/false,
4919 /*PartialOverloading=*/true);
4920 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004921 } else {
4922 // Lastly we check whether expression's type is function pointer or
4923 // function.
4924 QualType T = NakedFn->getType();
4925 if (!T->getPointeeType().isNull())
4926 T = T->getPointeeType();
4927
4928 if (auto FP = T->getAs<FunctionProtoType>()) {
4929 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00004930 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004931 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004932 Results.push_back(ResultCandidate(FP));
4933 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004934 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004935 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004936 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004937 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004938 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004939 QualType ParamType =
4940 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4941 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004942}
4943
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004944QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4945 SourceLocation Loc,
4946 ArrayRef<Expr *> Args,
4947 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004948 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004949 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004950
4951 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004952 CXXRecordDecl *RD =
4953 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004954 if (!RD)
4955 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004956
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004957 // FIXME: Provide support for member initializers.
4958 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004959
4960 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4961
Fangrui Song050229d2018-11-24 00:14:31 +00004962 for (NamedDecl *C : LookupConstructors(RD)) {
4963 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
4964 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
4965 CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004966 /*SuppressUsedConversions=*/false,
4967 /*PartialOverloading=*/true);
Fangrui Song050229d2018-11-24 00:14:31 +00004968 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4969 AddTemplateOverloadCandidate(
4970 FTD, DeclAccessPair::make(FTD, C->getAccess()),
4971 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
4972 /*SuppressUsedConversions=*/false,
4973 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004974 }
4975 }
4976
4977 SmallVector<ResultCandidate, 8> Results;
4978 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004979 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004980}
4981
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004982QualType Sema::ProduceCtorInitMemberSignatureHelp(
4983 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4984 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4985 if (!CodeCompleter)
4986 return QualType();
4987
4988 CXXConstructorDecl *Constructor =
4989 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4990 if (!Constructor)
4991 return QualType();
4992 // FIXME: Add support for Base class constructors as well.
4993 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4994 Constructor->getParent(), SS, TemplateTypeTy, II))
4995 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4996 MemberDecl->getLocation(), ArgExprs,
4997 OpenParLoc);
4998 return QualType();
4999}
5000
John McCall48871652010-08-21 09:40:31 +00005001void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
5002 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005003 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005004 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005005 return;
5006 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005007
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005008 CodeCompleteExpressionData Data;
5009 Data.PreferredType = VD->getType();
5010 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5011 Data.IgnoreDecls.push_back(VD);
5012
5013 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005014}
5015
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005016void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005017 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005018 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005019 mapCodeCompletionContext(*this, PCC_Statement));
5020 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5021 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005022
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005023 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5024 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005025 CodeCompleter->includeGlobals(),
5026 CodeCompleter->loadExternal());
5027
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005028 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005029
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005030 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005031 CodeCompletionBuilder Builder(Results.getAllocator(),
5032 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005033 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005034 if (Results.includeCodePatterns()) {
5035 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5036 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5037 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5038 Builder.AddPlaceholderChunk("statements");
5039 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5040 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5041 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005042 Results.AddResult(Builder.TakeString());
5043
5044 // "else if" block
5045 Builder.AddTypedTextChunk("else");
5046 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5047 Builder.AddTextChunk("if");
5048 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5049 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005050 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005051 Builder.AddPlaceholderChunk("condition");
5052 else
5053 Builder.AddPlaceholderChunk("expression");
5054 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005055 if (Results.includeCodePatterns()) {
5056 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5057 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5058 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5059 Builder.AddPlaceholderChunk("statements");
5060 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5061 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5062 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005063 Results.AddResult(Builder.TakeString());
5064
5065 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005066
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005067 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005068 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005069
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005070 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005071 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005072
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005073 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005074 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005075}
5076
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005077void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005078 bool EnteringContext, QualType BaseType) {
Eric Liu06d34022017-12-12 11:35:46 +00005079 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005080 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005081
Eric Liu06d34022017-12-12 11:35:46 +00005082 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5083 // "a::b::" is not corresponding to any context/namespace in the AST), since
5084 // it can be useful for global code completion which have information about
5085 // contexts/symbols that are not in the AST.
5086 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005087 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00005088 CC.setCXXScopeSpecifier(SS);
Eric Liu206740e2019-02-21 11:22:58 +00005089 // As SS is invalid, we try to collect accessible contexts from the current
5090 // scope with a dummy lookup so that the completion consumer can try to
5091 // guess what the specified scope is.
5092 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5093 CodeCompleter->getCodeCompletionTUInfo(), CC);
5094 if (S->getEntity()) {
5095 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5096 BaseType);
5097 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5098 /*IncludeGlobalScope=*/false,
5099 /*LoadExternal=*/false);
5100 }
5101 HandleCodeCompleteResults(this, CodeCompleter,
5102 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005103 return;
5104 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005105 // Always pretend to enter a context to ensure that a dependent type
5106 // resolves to a dependent record.
5107 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005108 if (!Ctx)
5109 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005110
5111 // Try to instantiate any non-dependent declaration contexts before
5112 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005113 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005114 return;
5115
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005116 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005117 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005118 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005119 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005120
Douglas Gregor3545ff42009-09-21 16:56:56 +00005121 // The "template" keyword can follow "::" in the grammar, but only
5122 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005123 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005124 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005125 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005126
5127 // Add calls to overridden virtual functions, if there are any.
5128 //
5129 // FIXME: This isn't wonderful, because we don't know whether we're actually
5130 // in a context that permits expressions. This is a general issue with
5131 // qualified-id completions.
5132 if (!EnteringContext)
5133 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005134 Results.ExitScope();
5135
Eric Liufead6ae2017-12-13 10:26:49 +00005136 if (CodeCompleter->includeNamespaceLevelDecls() ||
5137 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005138 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005139 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5140 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005141 /*IncludeDependentBases=*/true,
5142 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005143 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005144
Eric Liu06d34022017-12-12 11:35:46 +00005145 auto CC = Results.getCompletionContext();
5146 CC.setCXXScopeSpecifier(SS);
5147
5148 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
5149 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005150}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005151
5152void Sema::CodeCompleteUsing(Scope *S) {
5153 if (!CodeCompleter)
5154 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005155
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005156 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005157 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005158 // This can be both a using alias or using
5159 // declaration, in the former we expect a new name and a
5160 // symbol in the latter case.
5161 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005162 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005163 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005164
Douglas Gregor3545ff42009-09-21 16:56:56 +00005165 // If we aren't in class scope, we could see the "namespace" keyword.
5166 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005167 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005168
5169 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005170 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005171 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005172 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005173 CodeCompleter->includeGlobals(),
5174 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005175 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005176
5177 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5178 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005179}
5180
5181void Sema::CodeCompleteUsingDirective(Scope *S) {
5182 if (!CodeCompleter)
5183 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005184
Douglas Gregor3545ff42009-09-21 16:56:56 +00005185 // After "using namespace", we expect to see a namespace name or namespace
5186 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005187 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005188 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005189 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005190 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005191 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005192 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005193 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005194 CodeCompleter->includeGlobals(),
5195 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005196 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005197 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5198 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005199}
5200
Fangrui Song050229d2018-11-24 00:14:31 +00005201void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005202 if (!CodeCompleter)
5203 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005204
Ted Kremenekc37877d2013-10-08 17:08:03 +00005205 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005206 if (!S->getParent())
5207 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005208
Fangrui Song050229d2018-11-24 00:14:31 +00005209 bool SuppressedGlobalResults =
5210 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005211
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005212 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005213 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005214 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005215 ? CodeCompletionContext::CCC_Namespace
5216 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005217 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005218
Douglas Gregor0ac41382010-09-23 23:01:17 +00005219 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005220 // We only want to see those namespaces that have already been defined
5221 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005222 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005223 // definition of each namespace.
5224 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005225 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005226 NS(Ctx->decls_begin()),
5227 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005228 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005229 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005230
5231 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005232 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005233 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005234 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005235 NS = OrigToLatest.begin(),
5236 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005237 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005238 Results.AddResult(
5239 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5240 nullptr),
5241 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005242 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005243 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005244
Fangrui Song050229d2018-11-24 00:14:31 +00005245 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5246 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005247}
5248
Fangrui Song050229d2018-11-24 00:14:31 +00005249void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005250 if (!CodeCompleter)
5251 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005252
Douglas Gregor3545ff42009-09-21 16:56:56 +00005253 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005254 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005255 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005256 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005257 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005258 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005259 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005260 CodeCompleter->includeGlobals(),
5261 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005262 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5263 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005264}
5265
Douglas Gregorc811ede2009-09-18 20:05:18 +00005266void Sema::CodeCompleteOperatorName(Scope *S) {
5267 if (!CodeCompleter)
5268 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005269
John McCall276321a2010-08-25 06:19:51 +00005270 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005271 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005272 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005273 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005274 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005275 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005276
Douglas Gregor3545ff42009-09-21 16:56:56 +00005277 // Add the names of overloadable operators.
Fangrui Song050229d2018-11-24 00:14:31 +00005278#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5279 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005280 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005281#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005282
Douglas Gregor3545ff42009-09-21 16:56:56 +00005283 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005284 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005285 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005286 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005287 CodeCompleter->includeGlobals(),
5288 CodeCompleter->loadExternal());
5289
Douglas Gregor3545ff42009-09-21 16:56:56 +00005290 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005291 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005292 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005293
5294 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5295 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005296}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005297
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005298void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005299 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005300 if (!ConstructorD)
5301 return;
5302
5303 AdjustDeclIfTemplate(ConstructorD);
5304
Fangrui Song050229d2018-11-24 00:14:31 +00005305 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005306 if (!Constructor)
5307 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005308
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005309 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005310 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005311 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005312 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005313
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005314 // Fill in any already-initialized fields or base classes.
5315 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5316 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005317 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005318 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005319 InitializedBases.insert(Context.getCanonicalType(
5320 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005321 else
Fangrui Song050229d2018-11-24 00:14:31 +00005322 InitializedFields.insert(
5323 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005324 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005325
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005326 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005327 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005328 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005329 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005330
5331 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5332 CodeCompletionBuilder Builder(Results.getAllocator(),
5333 Results.getCodeCompletionTUInfo());
5334 Builder.AddTypedTextChunk(Name);
5335 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005336 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005337 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005338 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005339 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5340 Builder);
5341 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5342 return Builder.TakeString();
5343 };
5344 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5345 const NamedDecl *ND) {
5346 CodeCompletionBuilder Builder(Results.getAllocator(),
5347 Results.getCodeCompletionTUInfo());
5348 Builder.AddTypedTextChunk(Name);
5349 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5350 Builder.AddPlaceholderChunk(Type);
5351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5352 if (ND) {
5353 auto CCR = CodeCompletionResult(
5354 Builder.TakeString(), ND,
5355 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5356 if (isa<FieldDecl>(ND))
5357 CCR.CursorKind = CXCursor_MemberRef;
5358 return Results.AddResult(CCR);
5359 }
5360 return Results.AddResult(CodeCompletionResult(
5361 Builder.TakeString(),
5362 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5363 };
5364 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5365 const char *Name, const FieldDecl *FD) {
5366 if (!RD)
5367 return AddDefaultCtorInit(Name,
5368 FD ? Results.getAllocator().CopyString(
5369 FD->getType().getAsString(Policy))
5370 : Name,
5371 FD);
5372 auto Ctors = getConstructors(Context, RD);
5373 if (Ctors.begin() == Ctors.end())
5374 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005375 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005376 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5377 CCR.CursorKind = getCursorKindForDecl(Ctor);
5378 Results.AddResult(CCR);
5379 }
5380 };
5381 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5382 const char *BaseName =
5383 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5384 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5385 AddCtorsWithName(
5386 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5387 BaseName, nullptr);
5388 };
5389 auto AddField = [&](const FieldDecl *FD) {
5390 const char *FieldName =
5391 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5392 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5393 AddCtorsWithName(
5394 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5395 FieldName, FD);
5396 };
5397
Aaron Ballman574705e2014-03-13 15:41:46 +00005398 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005399 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5400 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005401 SawLastInitializer =
5402 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5403 Context.hasSameUnqualifiedType(
5404 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005405 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005406 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005407
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005408 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005409 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005410 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005411
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005412 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005413 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005414 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5415 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005416 SawLastInitializer =
5417 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5418 Context.hasSameUnqualifiedType(
5419 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005420 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005421 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005422
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005423 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005424 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005425 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005426
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005427 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005428 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005429 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5430 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005431 SawLastInitializer = !Initializers.empty() &&
5432 Initializers.back()->isAnyMemberInitializer() &&
5433 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005434 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005435 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005436
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005437 if (!Field->getDeclName())
5438 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005439
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005440 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005441 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005442 }
5443 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005444
Douglas Gregor0ac41382010-09-23 23:01:17 +00005445 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005446 Results.data(), Results.size());
5447}
5448
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005449/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005450static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005451 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005452 if (!DC)
5453 return false;
5454
5455 return DC->isFileContext();
5456}
5457
5458void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5459 bool AfterAmpersand) {
5460 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005461 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005462 CodeCompletionContext::CCC_Other);
5463 Results.EnterNewScope();
5464
5465 // Note what has already been captured.
5466 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5467 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005468 for (const auto &C : Intro.Captures) {
5469 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005470 IncludedThis = true;
5471 continue;
5472 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005473
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005474 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005475 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005476
Douglas Gregord8c61782012-02-15 15:34:24 +00005477 // Look for other capturable variables.
5478 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005479 for (const auto *D : S->decls()) {
5480 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005481 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005482 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005483
David Blaikie82e95a32014-11-19 07:49:47 +00005484 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005485 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005486 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005487 }
5488 }
5489
5490 // Add 'this', if it would be valid.
5491 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5492 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005493
Douglas Gregord8c61782012-02-15 15:34:24 +00005494 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005495
Douglas Gregord8c61782012-02-15 15:34:24 +00005496 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5497 Results.data(), Results.size());
5498}
5499
James Dennett596e4752012-06-14 03:11:41 +00005500/// Macro that optionally prepends an "@" to the string literal passed in via
5501/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005502#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005503
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005504static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005505 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005506 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005507 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005508 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005509
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005510 CodeCompletionBuilder Builder(Results.getAllocator(),
5511 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005512 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005513 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005514 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005515 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5516 Builder.AddPlaceholderChunk("property");
5517 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005518
Douglas Gregorf1934162010-01-13 21:24:21 +00005519 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005520 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005521 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5522 Builder.AddPlaceholderChunk("property");
5523 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005524 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005525}
5526
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005527static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005528 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005529 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005530
Douglas Gregorf1934162010-01-13 21:24:21 +00005531 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005532 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005533
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005534 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005535 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005536 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005537
Douglas Gregorf1934162010-01-13 21:24:21 +00005538 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005539 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005540
Douglas Gregorf1934162010-01-13 21:24:21 +00005541 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005542 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005543 }
5544}
5545
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005546static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005547 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005548 CodeCompletionBuilder Builder(Results.getAllocator(),
5549 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005550
Douglas Gregorf1934162010-01-13 21:24:21 +00005551 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005552 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005553 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5554 Builder.AddPlaceholderChunk("name");
5555 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005556
Douglas Gregorf4c33342010-05-28 00:22:41 +00005557 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005558 // @interface name
5559 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005560 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005561 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005562 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5563 Builder.AddPlaceholderChunk("class");
5564 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005565
Douglas Gregorf4c33342010-05-28 00:22:41 +00005566 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005567 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005568 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5569 Builder.AddPlaceholderChunk("protocol");
5570 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005571
Douglas Gregorf4c33342010-05-28 00:22:41 +00005572 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005573 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005574 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5575 Builder.AddPlaceholderChunk("class");
5576 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005577 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005578
Douglas Gregorf1934162010-01-13 21:24:21 +00005579 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005580 Builder.AddTypedTextChunk(
5581 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005582 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5583 Builder.AddPlaceholderChunk("alias");
5584 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5585 Builder.AddPlaceholderChunk("class");
5586 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005587
5588 if (Results.getSema().getLangOpts().Modules) {
5589 // @import name
5590 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5591 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5592 Builder.AddPlaceholderChunk("module");
5593 Results.AddResult(Result(Builder.TakeString()));
5594 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005595}
5596
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005597void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005598 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005599 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005600 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005601 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005602 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005603 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005604 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005605 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005606 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005607 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005608 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005609 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5610 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005611}
5612
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005613static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005614 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005615 CodeCompletionBuilder Builder(Results.getAllocator(),
5616 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005617
5618 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005619 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005620 if (Results.getSema().getLangOpts().CPlusPlus ||
5621 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005622 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005623 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005624 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005625 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5626 Builder.AddPlaceholderChunk("type-name");
5627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5628 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005629
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005630 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005631 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005632 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005633 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5634 Builder.AddPlaceholderChunk("protocol-name");
5635 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5636 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005637
5638 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005639 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005640 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005641 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5642 Builder.AddPlaceholderChunk("selector");
5643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5644 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005645
5646 // @"string"
5647 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005648 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005649 Builder.AddPlaceholderChunk("string");
5650 Builder.AddTextChunk("\"");
5651 Results.AddResult(Result(Builder.TakeString()));
5652
Douglas Gregor951de302012-07-17 23:24:47 +00005653 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005654 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005655 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005656 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005657 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5658 Results.AddResult(Result(Builder.TakeString()));
5659
Douglas Gregor951de302012-07-17 23:24:47 +00005660 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005661 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005662 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005663 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005664 Builder.AddChunk(CodeCompletionString::CK_Colon);
5665 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5666 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005667 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5668 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005669
Douglas Gregor951de302012-07-17 23:24:47 +00005670 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005671 Builder.AddResultTypeChunk("id");
5672 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005673 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005674 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5675 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005676}
5677
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005678static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005679 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005680 CodeCompletionBuilder Builder(Results.getAllocator(),
5681 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005682
Douglas Gregorf4c33342010-05-28 00:22:41 +00005683 if (Results.includeCodePatterns()) {
5684 // @try { statements } @catch ( declaration ) { statements } @finally
5685 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005686 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005687 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5688 Builder.AddPlaceholderChunk("statements");
5689 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5690 Builder.AddTextChunk("@catch");
5691 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5692 Builder.AddPlaceholderChunk("parameter");
5693 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5694 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5695 Builder.AddPlaceholderChunk("statements");
5696 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5697 Builder.AddTextChunk("@finally");
5698 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5699 Builder.AddPlaceholderChunk("statements");
5700 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5701 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005702 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005703
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005704 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005705 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005706 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5707 Builder.AddPlaceholderChunk("expression");
5708 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005709
Douglas Gregorf4c33342010-05-28 00:22:41 +00005710 if (Results.includeCodePatterns()) {
5711 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005712 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005713 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5714 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5715 Builder.AddPlaceholderChunk("expression");
5716 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5717 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5718 Builder.AddPlaceholderChunk("statements");
5719 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5720 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005721 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005722}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005723
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005724static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005725 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005726 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005727 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5728 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5729 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005730 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005731 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005732}
5733
5734void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005735 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005736 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005737 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005738 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005739 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005740 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005741 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5742 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005743}
5744
5745void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005746 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005747 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005748 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005749 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005750 AddObjCStatementResults(Results, false);
5751 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005752 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005753 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5754 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005755}
5756
5757void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005758 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005759 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005760 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005761 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005762 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005763 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005764 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5765 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005766}
5767
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005768/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005769/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005770static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005771 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005772 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005773 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005774
Bill Wendling44426052012-12-20 19:22:21 +00005775 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005776
Douglas Gregore6078da2009-11-19 00:14:45 +00005777 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005778 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5779 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005780 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005781
Jordan Rose53cb2f32012-08-20 20:01:13 +00005782 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00005783 unsigned AssignCopyRetMask =
5784 Attributes &
5785 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
5786 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
5787 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
5788 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005789 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005790 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005791 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005792 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5793 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005794 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005795
Douglas Gregore6078da2009-11-19 00:14:45 +00005796 return false;
5797}
5798
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005799void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005800 if (!CodeCompleter)
5801 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005802
Bill Wendling44426052012-12-20 19:22:21 +00005803 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005804
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005805 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005806 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005807 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005808 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005809 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005810 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005811 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005812 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005813 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005814 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5815 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005816 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005817 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005818 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005819 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005820 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005821 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005822 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005823 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005824 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005825 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005826 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005827 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005828
5829 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005830 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005831 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005832 Results.AddResult(CodeCompletionResult("weak"));
5833
Bill Wendling44426052012-12-20 19:22:21 +00005834 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005835 CodeCompletionBuilder Setter(Results.getAllocator(),
5836 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005837 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005838 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005839 Setter.AddPlaceholderChunk("method");
5840 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005841 }
Bill Wendling44426052012-12-20 19:22:21 +00005842 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005843 CodeCompletionBuilder Getter(Results.getAllocator(),
5844 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005845 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005846 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005847 Getter.AddPlaceholderChunk("method");
5848 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005849 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005850 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5851 Results.AddResult(CodeCompletionResult("nonnull"));
5852 Results.AddResult(CodeCompletionResult("nullable"));
5853 Results.AddResult(CodeCompletionResult("null_unspecified"));
5854 Results.AddResult(CodeCompletionResult("null_resettable"));
5855 }
Steve Naroff936354c2009-10-08 21:55:05 +00005856 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005857 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5858 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005859}
Steve Naroffeae65032009-11-07 02:08:14 +00005860
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005861/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005862/// via code completion.
5863enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005864 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5865 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00005866 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005867};
5868
Fangrui Song050229d2018-11-24 00:14:31 +00005869static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005870 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005871 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005872 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005873 if (NumSelIdents > Sel.getNumArgs())
5874 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005875
Douglas Gregor67c692c2010-08-26 15:07:07 +00005876 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00005877 case MK_Any:
5878 break;
5879 case MK_ZeroArgSelector:
5880 return Sel.isUnarySelector();
5881 case MK_OneArgSelector:
5882 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005883 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005884
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005885 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5886 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005887
Douglas Gregor67c692c2010-08-26 15:07:07 +00005888 for (unsigned I = 0; I != NumSelIdents; ++I)
5889 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5890 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005891
Douglas Gregor67c692c2010-08-26 15:07:07 +00005892 return true;
5893}
5894
Douglas Gregorc8537c52009-11-19 07:41:15 +00005895static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5896 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005897 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005898 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005899 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005900 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005901}
Douglas Gregor1154e272010-09-16 16:06:31 +00005902
Fangrui Song050229d2018-11-24 00:14:31 +00005903/// A set of selectors, which is used to avoid introducing multiple
5904/// completions with the same selector into the result set.
5905typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00005906
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005907/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005908/// container to the set of results.
5909///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005910/// The container will be a class, protocol, category, or implementation of
5911/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005912/// the superclasses of classes along with their categories, protocols, and
5913/// implementations.
5914///
5915/// \param Container the container in which we'll look to find methods.
5916///
James Dennett596e4752012-06-14 03:11:41 +00005917/// \param WantInstanceMethods Whether to add instance methods (only); if
5918/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005919///
5920/// \param CurContext the context in which we're performing the lookup that
5921/// finds methods.
5922///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005923/// \param AllowSameLength Whether we allow a method to be added to the list
5924/// when it has the same number of parameters as we have selector identifiers.
5925///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005926/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005927static void AddObjCMethods(ObjCContainerDecl *Container,
5928 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005929 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005930 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005931 VisitedSelectorSet &Selectors, bool AllowSameLength,
5932 ResultBuilder &Results, bool InOriginalClass = true,
5933 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005934 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005935 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005936 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005937 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00005938 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005939 // The instance methods on the root class can be messaged via the
5940 // metaclass.
5941 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005942 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005943 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005944 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005945 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005946 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005947
David Blaikie82e95a32014-11-19 07:49:47 +00005948 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005949 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005950
5951 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005952 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005953 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005954 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00005955 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00005956 Results.MaybeAddResult(R, CurContext);
5957 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005958 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005959
Douglas Gregorf37c9492010-09-16 15:34:59 +00005960 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005961 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005962 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00005963 const ObjCList<ObjCProtocolDecl> &Protocols =
5964 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005965 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005966 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005967 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005968 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5969 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005970 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005971 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005972
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005973 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005974 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005975
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005976 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005977 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005978 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5979 Selectors, AllowSameLength, Results, false, IsRootClass);
5980
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005981 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00005982 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005983 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005984 CurContext, Selectors, AllowSameLength, Results,
5985 InOriginalClass, IsRootClass);
5986
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005987 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00005988 const ObjCList<ObjCProtocolDecl> &Protocols =
5989 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005990 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5991 E = Protocols.end();
5992 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005993 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5994 Selectors, AllowSameLength, Results, false, IsRootClass);
5995
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005996 // Add methods in category implementations.
5997 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005998 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5999 Selectors, AllowSameLength, Results, InOriginalClass,
6000 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006001 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006002
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006003 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006004 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006005 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006006 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6007 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6008 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006009
6010 // Add methods in our implementation, if any.
6011 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006012 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6013 Selectors, AllowSameLength, Results, InOriginalClass,
6014 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006015}
6016
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006017void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006018 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006019 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006020 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006021 if (ObjCCategoryDecl *Category =
6022 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006023 Class = Category->getClassInterface();
6024
6025 if (!Class)
6026 return;
6027 }
6028
6029 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006030 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006031 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006032 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006033 Results.EnterNewScope();
6034
Douglas Gregor1154e272010-09-16 16:06:31 +00006035 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006036 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006037 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006038 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006039 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6040 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006041}
6042
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006043void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006044 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006045 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006046 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006047 if (ObjCCategoryDecl *Category =
6048 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006049 Class = Category->getClassInterface();
6050
6051 if (!Class)
6052 return;
6053 }
6054
6055 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006056 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006057 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006058 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006059 Results.EnterNewScope();
6060
Douglas Gregor1154e272010-09-16 16:06:31 +00006061 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006062 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6063 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006064
6065 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006066 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6067 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006068}
6069
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006070void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6071 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006072 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006073 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006074 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006075 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006076
Douglas Gregor99fa2642010-08-24 01:06:58 +00006077 // Add context-sensitive, Objective-C parameter-passing keywords.
6078 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006079 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006080 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6081 Results.AddResult("in");
6082 Results.AddResult("inout");
6083 AddedInOut = true;
6084 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006085 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006086 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6087 Results.AddResult("out");
6088 if (!AddedInOut)
6089 Results.AddResult("inout");
6090 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006091 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006092 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6093 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006094 Results.AddResult("bycopy");
6095 Results.AddResult("byref");
6096 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006097 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006098 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6099 Results.AddResult("nonnull");
6100 Results.AddResult("nullable");
6101 Results.AddResult("null_unspecified");
6102 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006103
6104 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006105 // identifier IBAction refers to a macro, provide a completion item for
6106 // an action, e.g.,
6107 // IBAction)<#selector#>:(id)sender
6108 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006109 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006110 CodeCompletionBuilder Builder(Results.getAllocator(),
6111 Results.getCodeCompletionTUInfo(),
6112 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006113 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006114 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006115 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006116 Builder.AddChunk(CodeCompletionString::CK_Colon);
6117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006118 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006119 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006120 Builder.AddTextChunk("sender");
6121 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6122 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006123
6124 // If we're completing the return type, provide 'instancetype'.
6125 if (!IsParameter) {
6126 Results.AddResult(CodeCompletionResult("instancetype"));
6127 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006128
Douglas Gregor99fa2642010-08-24 01:06:58 +00006129 // Add various builtin type names and specifiers.
6130 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6131 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006132
Douglas Gregor99fa2642010-08-24 01:06:58 +00006133 // Add the various type names
6134 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6135 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6136 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006137 CodeCompleter->includeGlobals(),
6138 CodeCompleter->loadExternal());
6139
Douglas Gregor99fa2642010-08-24 01:06:58 +00006140 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006141 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006142
Eric Liuf5ba09f2018-07-04 10:01:18 +00006143 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006144 Results.data(), Results.size());
6145}
6146
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006147/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006148/// that it has some more-specific class type based on knowledge of
6149/// common uses of Objective-C. This routine returns that class type,
6150/// or NULL if no better result could be determined.
6151static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006152 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006153 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006154 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006155
6156 Selector Sel = Msg->getSelector();
6157 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006158 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006159
6160 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6161 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006162 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006163
6164 ObjCMethodDecl *Method = Msg->getMethodDecl();
6165 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006166 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006167
6168 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006169 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006170 switch (Msg->getReceiverKind()) {
6171 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006172 if (const ObjCObjectType *ObjType =
6173 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006174 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006175 break;
6176
6177 case ObjCMessageExpr::Instance: {
6178 QualType T = Msg->getInstanceReceiver()->getType();
6179 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6180 IFace = Ptr->getInterfaceDecl();
6181 break;
6182 }
6183
6184 case ObjCMessageExpr::SuperInstance:
6185 case ObjCMessageExpr::SuperClass:
6186 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006187 }
6188
6189 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006190 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006191
6192 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6193 if (Method->isInstanceMethod())
6194 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006195 .Case("retain", IFace)
6196 .Case("strong", IFace)
6197 .Case("autorelease", IFace)
6198 .Case("copy", IFace)
6199 .Case("copyWithZone", IFace)
6200 .Case("mutableCopy", IFace)
6201 .Case("mutableCopyWithZone", IFace)
6202 .Case("awakeFromCoder", IFace)
6203 .Case("replacementObjectFromCoder", IFace)
6204 .Case("class", IFace)
6205 .Case("classForCoder", IFace)
6206 .Case("superclass", Super)
6207 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006208
6209 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006210 .Case("new", IFace)
6211 .Case("alloc", IFace)
6212 .Case("allocWithZone", IFace)
6213 .Case("class", IFace)
6214 .Case("superclass", Super)
6215 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006216}
6217
Douglas Gregor6fc04132010-08-27 15:10:57 +00006218// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006219// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006220// function.
6221///
6222/// \param S The semantic analysis object.
6223///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006224/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006225/// the "super" keyword. Otherwise, we just need to provide the arguments.
6226///
6227/// \param SelIdents The identifiers in the selector that have already been
6228/// provided as arguments for a send to "super".
6229///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006230/// \param Results The set of results to augment.
6231///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006232/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006233/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006234static ObjCMethodDecl *
6235AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6236 ArrayRef<IdentifierInfo *> SelIdents,
6237 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006238 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6239 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006240 return nullptr;
6241
Douglas Gregor6fc04132010-08-27 15:10:57 +00006242 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6243 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006244 return nullptr;
6245
Douglas Gregor6fc04132010-08-27 15:10:57 +00006246 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006247 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006248 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6249 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006250 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006251 CurMethod->isInstanceMethod());
6252
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006253 // Check in categories or class extensions.
6254 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006255 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006256 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006257 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006258 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006259 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006260 }
6261 }
6262
Douglas Gregor6fc04132010-08-27 15:10:57 +00006263 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006264 return nullptr;
6265
Douglas Gregor6fc04132010-08-27 15:10:57 +00006266 // Check whether the superclass method has the same signature.
6267 if (CurMethod->param_size() != SuperMethod->param_size() ||
6268 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006269 return nullptr;
6270
Douglas Gregor6fc04132010-08-27 15:10:57 +00006271 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006272 CurPEnd = CurMethod->param_end(),
6273 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006274 CurP != CurPEnd; ++CurP, ++SuperP) {
6275 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006276 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006277 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006278 return nullptr;
6279
Douglas Gregor6fc04132010-08-27 15:10:57 +00006280 // Make sure we have a parameter name to forward!
6281 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006282 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006283 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006284
Douglas Gregor6fc04132010-08-27 15:10:57 +00006285 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006286 CodeCompletionBuilder Builder(Results.getAllocator(),
6287 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006288
Douglas Gregor6fc04132010-08-27 15:10:57 +00006289 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006290 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006291 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006292
6293 // If we need the "super" keyword, add it (plus some spacing).
6294 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006295 Builder.AddTypedTextChunk("super");
6296 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006297 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006298
Douglas Gregor6fc04132010-08-27 15:10:57 +00006299 Selector Sel = CurMethod->getSelector();
6300 if (Sel.isUnarySelector()) {
6301 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006302 Builder.AddTextChunk(
6303 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006304 else
Fangrui Song050229d2018-11-24 00:14:31 +00006305 Builder.AddTypedTextChunk(
6306 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006307 } else {
6308 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6309 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006310 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006311 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006312
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006313 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006314 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006315 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006316 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006317 Builder.AddTextChunk(
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 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006322 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006323 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006324 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006325 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006326 }
6327 }
6328 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006329
Douglas Gregor78254c82012-03-27 23:34:16 +00006330 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6331 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006332 return SuperMethod;
6333}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006334
Douglas Gregora817a192010-05-27 23:06:34 +00006335void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006336 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006337 ResultBuilder Results(
6338 *this, CodeCompleter->getAllocator(),
6339 CodeCompleter->getCodeCompletionTUInfo(),
6340 CodeCompletionContext::CCC_ObjCMessageReceiver,
6341 getLangOpts().CPlusPlus11
6342 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6343 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006344
Douglas Gregora817a192010-05-27 23:06:34 +00006345 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6346 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006347 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006348 CodeCompleter->includeGlobals(),
6349 CodeCompleter->loadExternal());
6350
Douglas Gregora817a192010-05-27 23:06:34 +00006351 // If we are in an Objective-C method inside a class that has a superclass,
6352 // add "super" as an option.
6353 if (ObjCMethodDecl *Method = getCurMethodDecl())
6354 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006355 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006356 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006357
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006358 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006359 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006360
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006361 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006362 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006363
Douglas Gregora817a192010-05-27 23:06:34 +00006364 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006365
Douglas Gregora817a192010-05-27 23:06:34 +00006366 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006367 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006368 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006369 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006370}
6371
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006372void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006373 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006374 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006375 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006376 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6377 // Figure out which interface we're in.
6378 CDecl = CurMethod->getClassInterface();
6379 if (!CDecl)
6380 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006381
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006382 // Find the superclass of this class.
6383 CDecl = CDecl->getSuperClass();
6384 if (!CDecl)
6385 return;
6386
6387 if (CurMethod->isInstanceMethod()) {
6388 // We are inside an instance method, which means that the message
6389 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006390 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006391 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006392 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006393 }
6394
6395 // Fall through to send to the superclass in CDecl.
6396 } else {
6397 // "super" may be the name of a type or variable. Figure out which
6398 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006399 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006400 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006401 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6402 // "super" names an interface. Use it.
6403 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006404 if (const ObjCObjectType *Iface =
6405 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006406 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006407 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6408 // "super" names an unresolved type; we can't be more specific.
6409 } else {
6410 // Assume that "super" names some kind of value and parse that way.
6411 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006412 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006413 UnqualifiedId id;
6414 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006415 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6416 /*HasTrailingLParen=*/false,
6417 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006418 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006419 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006420 }
6421
6422 // Fall through
6423 }
6424
John McCallba7bf592010-08-24 05:47:05 +00006425 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006426 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006427 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006428 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006429 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006430 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006431}
6432
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006433/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006434/// send, determine the preferred type (if any) for that argument expression.
6435static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6436 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006437 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006438 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006439
Douglas Gregor74661272010-09-21 00:03:25 +00006440 QualType PreferredType;
6441 unsigned BestPriority = CCP_Unlikely * 2;
6442 Result *ResultsData = Results.data();
6443 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6444 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006445 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006446 isa<ObjCMethodDecl>(R.Declaration)) {
6447 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006448 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006449 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006450 QualType MyPreferredType =
6451 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006452 if (R.Priority < BestPriority || PreferredType.isNull()) {
6453 BestPriority = R.Priority;
6454 PreferredType = MyPreferredType;
6455 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6456 MyPreferredType)) {
6457 PreferredType = QualType();
6458 }
6459 }
6460 }
6461 }
6462 }
6463
6464 return PreferredType;
6465}
6466
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006467static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006468 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006469 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006470 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006471 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006472 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006473 ObjCInterfaceDecl *CDecl = nullptr;
6474
Douglas Gregor8ce33212009-11-17 17:59:40 +00006475 // If the given name refers to an interface type, retrieve the
6476 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006477 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006478 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006479 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006480 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6481 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006482 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006483
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006484 // Add all of the factory methods in this Objective-C class, its protocols,
6485 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006486 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006487
6488 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006489 // completion.
6490 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006491 if (ObjCMethodDecl *SuperMethod =
6492 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006493 Results.Ignore(SuperMethod);
6494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006495
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006496 // If we're inside an Objective-C method definition, prefer its selector to
6497 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006498 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006499 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006500
Douglas Gregor1154e272010-09-16 16:06:31 +00006501 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006502 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006503 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6504 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006505 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006506 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006507
Douglas Gregord720daf2010-04-06 17:30:22 +00006508 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006509 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006510 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006511 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006512 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006513 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006514 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006515 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006516 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006517
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006518 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006519 }
6520 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006521
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006522 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006523 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006524 M != MEnd; ++M) {
6525 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006526 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006527 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006528 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006529
Nico Weber2e0c8f72014-12-27 03:58:08 +00006530 Result R(MethList->getMethod(),
6531 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006532 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006533 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006534 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006535 }
6536 }
6537 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006538
6539 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006540}
Douglas Gregor6285f752010-04-06 16:40:00 +00006541
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006542void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006543 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006544 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006545 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006546
Douglas Gregor63745d52011-07-21 01:05:26 +00006547 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006548
Fangrui Song050229d2018-11-24 00:14:31 +00006549 ResultBuilder Results(
6550 *this, CodeCompleter->getAllocator(),
6551 CodeCompleter->getCodeCompletionTUInfo(),
6552 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6553 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006554
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006555 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006556 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006557
6558 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006559 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006560 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006561 // code-complete the expression using the corresponding parameter type as
6562 // our preferred type, improving completion results.
6563 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006564 QualType PreferredType =
6565 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006566 if (PreferredType.isNull())
6567 CodeCompleteOrdinaryName(S, PCC_Expression);
6568 else
6569 CodeCompleteExpression(S, PreferredType);
6570 return;
6571 }
6572
Fangrui Song050229d2018-11-24 00:14:31 +00006573 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006574 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006575}
6576
Richard Trieu2bd04012011-09-09 02:00:50 +00006577void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006578 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006579 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006580 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006581 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006582
Steve Naroffeae65032009-11-07 02:08:14 +00006583 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006584
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006585 // If necessary, apply function/array conversion to the receiver.
6586 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006587 if (RecExpr) {
6588 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6589 if (Conv.isInvalid()) // conversion failed. bail.
6590 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006591 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006592 }
Fangrui Song050229d2018-11-24 00:14:31 +00006593 QualType ReceiverType = RecExpr
6594 ? RecExpr->getType()
6595 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006596 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006597 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006598
Douglas Gregordc520b02010-11-08 21:12:30 +00006599 // If we're messaging an expression with type "id" or "Class", check
6600 // whether we know something special about the receiver that allows
6601 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006602 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006603 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6604 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006605 return CodeCompleteObjCClassMessage(
6606 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6607 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006608
Fangrui Song050229d2018-11-24 00:14:31 +00006609 ReceiverType =
6610 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006611 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006612 } else if (RecExpr && getLangOpts().CPlusPlus) {
6613 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6614 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006615 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006616 ReceiverType = RecExpr->getType();
6617 }
6618 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006619
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006620 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006621 ResultBuilder Results(
6622 *this, CodeCompleter->getAllocator(),
6623 CodeCompleter->getCodeCompletionTUInfo(),
6624 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6625 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006626
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006627 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006628
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006629 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006630 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006631 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006632 if (ObjCMethodDecl *SuperMethod =
6633 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006634 Results.Ignore(SuperMethod);
6635 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006636
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006637 // If we're inside an Objective-C method definition, prefer its selector to
6638 // others.
6639 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6640 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006641
Douglas Gregor1154e272010-09-16 16:06:31 +00006642 // Keep track of the selectors we've already added.
6643 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006644
Douglas Gregora3329fa2009-11-18 00:06:18 +00006645 // Handle messages to Class. This really isn't a message to an instance
6646 // method, so we treat it the same way we would treat a message send to a
6647 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006648 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006649 ReceiverType->isObjCQualifiedClassType()) {
6650 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6651 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006652 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6653 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006654 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006655 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006656 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006657 else if (const ObjCObjectPointerType *QualID =
6658 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006659 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006660 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006661 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6662 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006663 }
6664 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006665 else if (const ObjCObjectPointerType *IFacePtr =
6666 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006667 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006668 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006669 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006670
Douglas Gregora3329fa2009-11-18 00:06:18 +00006671 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006672 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006673 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6674 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006675 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006676 // Handle messages to "id".
6677 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006678 // We're messaging "id", so provide all instance methods we know
6679 // about as code-completion results.
6680
6681 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006682 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006683 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006684 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6685 I != N; ++I) {
6686 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006687 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006688 continue;
6689
Sebastian Redl75d8a322010-08-02 23:18:59 +00006690 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006691 }
6692 }
6693
Sebastian Redl75d8a322010-08-02 23:18:59 +00006694 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6695 MEnd = MethodPool.end();
6696 M != MEnd; ++M) {
6697 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006698 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006699 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006700 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006701
Nico Weber2e0c8f72014-12-27 03:58:08 +00006702 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006703 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006704
Nico Weber2e0c8f72014-12-27 03:58:08 +00006705 Result R(MethList->getMethod(),
6706 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006707 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006708 R.AllParametersAreInformative = false;
6709 Results.MaybeAddResult(R, CurContext);
6710 }
6711 }
6712 }
Steve Naroffeae65032009-11-07 02:08:14 +00006713 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006714
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006715 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006716 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006717 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006718 // code-complete the expression using the corresponding parameter type as
6719 // our preferred type, improving completion results.
6720 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006721 QualType PreferredType =
6722 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006723 if (PreferredType.isNull())
6724 CodeCompleteOrdinaryName(S, PCC_Expression);
6725 else
6726 CodeCompleteExpression(S, PreferredType);
6727 return;
6728 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006729
Fangrui Song050229d2018-11-24 00:14:31 +00006730 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6731 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006732}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006733
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006734void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006735 DeclGroupPtrTy IterationVar) {
6736 CodeCompleteExpressionData Data;
6737 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006738
Douglas Gregor68762e72010-08-23 21:17:50 +00006739 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006740 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006741 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6742 if (*I)
6743 Data.IgnoreDecls.push_back(*I);
6744 }
6745 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006746
Douglas Gregor68762e72010-08-23 21:17:50 +00006747 CodeCompleteExpression(S, Data);
6748}
6749
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006750void Sema::CodeCompleteObjCSelector(Scope *S,
6751 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006752 // If we have an external source, load the entire class method
6753 // pool from the AST file.
6754 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00006755 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
6756 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006757 Selector Sel = ExternalSource->GetExternalSelector(I);
6758 if (Sel.isNull() || MethodPool.count(Sel))
6759 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006760
Douglas Gregor67c692c2010-08-26 15:07:07 +00006761 ReadMethodPool(Sel);
6762 }
6763 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006764
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006765 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006766 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006767 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006768 Results.EnterNewScope();
6769 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006770 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006771 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006772
Douglas Gregor67c692c2010-08-26 15:07:07 +00006773 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006774 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006775 continue;
6776
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006777 CodeCompletionBuilder Builder(Results.getAllocator(),
6778 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006779 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006780 Builder.AddTypedTextChunk(
6781 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006782 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006783 continue;
6784 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006785
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006786 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006787 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006788 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006789 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006790 Builder.AddInformativeChunk(
6791 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006792 Accumulator.clear();
6793 }
6794 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006795
Benjamin Kramer632500c2011-07-26 16:59:25 +00006796 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006797 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006798 }
Fangrui Song050229d2018-11-24 00:14:31 +00006799 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006800 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006801 }
6802 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006803
6804 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006805 Results.data(), Results.size());
6806}
6807
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006808/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006809/// (translation unit) context.
6810static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006811 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006812 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006813 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006814
Aaron Ballman629afae2014-03-07 19:56:05 +00006815 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006816 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006817 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006818 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00006819 Results.AddResult(
6820 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
6821 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006822 }
6823}
6824
Craig Topper883dd332015-12-24 23:58:11 +00006825void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00006826 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006827 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006828 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006829 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006830
Chandler Carruthede11632016-11-04 06:06:50 +00006831 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006832 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006833
Douglas Gregora3b23b02010-12-09 21:44:02 +00006834 // Tell the result set to ignore all of the protocols we have
6835 // already seen.
6836 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006837 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00006838 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006839 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006840
Douglas Gregora3b23b02010-12-09 21:44:02 +00006841 // Add all protocols.
6842 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6843 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006844
Douglas Gregora3b23b02010-12-09 21:44:02 +00006845 Results.ExitScope();
6846 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006847
6848 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6849 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006850}
6851
6852void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006853 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006854 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006855 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006856
Chandler Carruthede11632016-11-04 06:06:50 +00006857 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006858 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006859
Douglas Gregora3b23b02010-12-09 21:44:02 +00006860 // Add all protocols.
6861 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6862 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006863
Douglas Gregora3b23b02010-12-09 21:44:02 +00006864 Results.ExitScope();
6865 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006866
6867 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6868 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006869}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006870
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006871/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006872/// the given (translation unit) context.
6873static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6874 bool OnlyForwardDeclarations,
6875 bool OnlyUnimplemented,
6876 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006877 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006878
Aaron Ballman629afae2014-03-07 19:56:05 +00006879 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006880 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006881 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006882 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006883 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00006884 Results.AddResult(
6885 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
6886 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006887 }
6888}
6889
Eric Liuf5ba09f2018-07-04 10:01:18 +00006890void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006891 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006892 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006893 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006894 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006895
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006896 if (CodeCompleter->includeGlobals()) {
6897 // Add all classes.
6898 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6899 false, Results);
6900 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006901
Douglas Gregor49c22a72009-11-18 16:26:39 +00006902 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006903
Eric Liuf5ba09f2018-07-04 10:01:18 +00006904 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6905 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006906}
6907
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006908void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006909 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006910 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006911 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006912 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006913 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006914
Douglas Gregor49c22a72009-11-18 16:26:39 +00006915 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00006916 NamedDecl *CurClass =
6917 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006918 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006919 Results.Ignore(CurClass);
6920
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006921 if (CodeCompleter->includeGlobals()) {
6922 // Add all classes.
6923 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6924 false, Results);
6925 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006926
Douglas Gregor49c22a72009-11-18 16:26:39 +00006927 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006928
Eric Liuf5ba09f2018-07-04 10:01:18 +00006929 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6930 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006931}
6932
Eric Liuf5ba09f2018-07-04 10:01:18 +00006933void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006934 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006935 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006936 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006937 Results.EnterNewScope();
6938
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006939 if (CodeCompleter->includeGlobals()) {
6940 // Add all unimplemented classes.
6941 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6942 true, Results);
6943 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006944
Douglas Gregor49c22a72009-11-18 16:26:39 +00006945 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006946
Eric Liuf5ba09f2018-07-04 10:01:18 +00006947 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6948 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006949}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006950
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006951void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006952 IdentifierInfo *ClassName,
6953 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006954 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006955
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006956 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006957 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006958 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006959
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006960 // Ignore any categories we find that have already been implemented by this
6961 // interface.
6962 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00006963 NamedDecl *CurClass =
6964 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
6965 if (ObjCInterfaceDecl *Class =
6966 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006967 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006968 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006969 }
6970
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006971 // Add all of the categories we know about.
6972 Results.EnterNewScope();
6973 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006974 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006975 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006976 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00006977 Results.AddResult(
6978 Result(Category, Results.getBasePriority(Category), nullptr),
6979 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006980 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006981
6982 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6983 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006984}
6985
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006986void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006987 IdentifierInfo *ClassName,
6988 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006989 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006990
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006991 // Find the corresponding interface. If we couldn't find the interface, the
6992 // program itself is ill-formed. However, we'll try to be helpful still by
6993 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00006994 NamedDecl *CurClass =
6995 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006996 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6997 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006998 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006999
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007000 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007001 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007002 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007003
7004 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007005 // declarations in this class and any of its superclasses, except for
7006 // already-implemented categories in the class itself.
7007 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7008 Results.EnterNewScope();
7009 bool IgnoreImplemented = true;
7010 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007011 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007012 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007013 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007014 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7015 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007016 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007017
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007018 Class = Class->getSuperClass();
7019 IgnoreImplemented = false;
7020 }
7021 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007022
7023 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7024 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007025}
Douglas Gregor5d649882009-11-18 22:32:06 +00007026
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007027void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007028 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007029 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007030 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007031
7032 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007033 ObjCContainerDecl *Container =
7034 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7035 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7036 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007037 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007038
7039 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007040 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007041 for (const auto *D : Container->decls())
7042 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007043 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007044
Douglas Gregor5d649882009-11-18 22:32:06 +00007045 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007046 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007047 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007048 if (ObjCImplementationDecl *ClassImpl =
7049 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007050 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007051 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007052 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007053 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007054 AddObjCProperties(CCContext,
7055 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007056 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007057 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007058 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007059
7060 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7061 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007062}
7063
Fangrui Song050229d2018-11-24 00:14:31 +00007064void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7065 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007066 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007067 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007068 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007069 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007070
7071 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007072 ObjCContainerDecl *Container =
7073 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7074 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7075 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007076 return;
7077
Douglas Gregor5d649882009-11-18 22:32:06 +00007078 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007079 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007080 if (ObjCImplementationDecl *ClassImpl =
7081 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007082 Class = ClassImpl->getClassInterface();
7083 else
Fangrui Song050229d2018-11-24 00:14:31 +00007084 Class = cast<ObjCCategoryImplDecl>(Container)
7085 ->getCategoryDecl()
7086 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007087
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007088 // Determine the type of the property we're synthesizing.
7089 QualType PropertyType = Context.getObjCIdType();
7090 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007091 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7092 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007093 PropertyType =
7094 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007095
7096 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007097 Results.setPreferredType(PropertyType);
7098 }
7099 }
7100
Douglas Gregor5d649882009-11-18 22:32:06 +00007101 // Add all of the instance variables in this class and its superclasses.
7102 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007103 bool SawSimilarlyNamedIvar = false;
7104 std::string NameWithPrefix;
7105 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007106 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007107 std::string NameWithSuffix = PropertyName->getName().str();
7108 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007109 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007110 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007111 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007112 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7113 CurContext, nullptr, false);
7114
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007115 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007116 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007117 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007118 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007119 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007120 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007121
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007122 // Reduce the priority of this result by one, to give it a slight
7123 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007124 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007125 Results.data()[Results.size() - 1].Kind ==
7126 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007127 Results.data()[Results.size() - 1].Declaration == Ivar)
7128 Results.data()[Results.size() - 1].Priority--;
7129 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007130 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007131 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007132
Douglas Gregor331faa02011-04-18 14:13:53 +00007133 if (!SawSimilarlyNamedIvar) {
7134 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007135 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007136 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007137 typedef CodeCompletionResult Result;
7138 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007139 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007140 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007141
Douglas Gregor75acd922011-09-27 23:30:47 +00007142 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007143 Builder.AddResultTypeChunk(
7144 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007145 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007146 Results.AddResult(
7147 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007148 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007149
Douglas Gregor5d649882009-11-18 22:32:06 +00007150 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007151
7152 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7153 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007154}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007155
Douglas Gregor416b5752010-08-25 01:08:01 +00007156// Mapping from selectors to the methods that implement that selector, along
7157// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007158typedef llvm::DenseMap<Selector,
7159 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7160 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007161
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007162/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007163/// (and its superclasses, protocols, etc.) that meet the given
7164/// criteria. Insert those methods into the map of known methods,
7165/// indexed by selector so they can be easily found.
7166static void FindImplementableMethods(ASTContext &Context,
7167 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007168 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007169 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007170 KnownMethodsMap &KnownMethods,
7171 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007172 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007173 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007174 if (!IFace->hasDefinition())
7175 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007176
7177 IFace = IFace->getDefinition();
7178 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007179
Fangrui Song050229d2018-11-24 00:14:31 +00007180 const ObjCList<ObjCProtocolDecl> &Protocols =
7181 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007182 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007183 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007184 I != E; ++I)
7185 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007186 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007187
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007188 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007189 for (auto *Cat : IFace->visible_categories()) {
7190 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007191 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007192 }
7193
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007194 // Visit the superclass.
7195 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007196 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007197 WantInstanceMethods, ReturnType, KnownMethods,
7198 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007199 }
7200
7201 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7202 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007203 const ObjCList<ObjCProtocolDecl> &Protocols =
7204 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007205 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007206 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007207 I != E; ++I)
7208 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007209 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007210
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007211 // If this category is the original class, jump to the interface.
7212 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007213 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007214 WantInstanceMethods, ReturnType, KnownMethods,
7215 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007216 }
7217
7218 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007219 // Make sure we have a definition; that's what we'll walk.
7220 if (!Protocol->hasDefinition())
7221 return;
7222 Protocol = Protocol->getDefinition();
7223 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007224
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007225 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007226 const ObjCList<ObjCProtocolDecl> &Protocols =
7227 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007228 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007229 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007230 I != E; ++I)
7231 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7232 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007233 }
7234
7235 // Add methods in this container. This operation occurs last because
7236 // we want the methods from this container to override any methods
7237 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007238 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007239 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007240 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007241 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007242 continue;
7243
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007244 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007245 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007246 }
7247 }
7248}
7249
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007250/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007251/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007252static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007253 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007254 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007255 CodeCompletionBuilder &Builder) {
7256 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007257 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007258 if (!Quals.empty())
7259 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007260 Builder.AddTextChunk(
7261 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007262 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7263}
7264
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007265/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007266/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007267static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007268 if (!Class)
7269 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007270
Douglas Gregor669a25a2011-02-17 00:22:45 +00007271 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7272 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007273
Douglas Gregor669a25a2011-02-17 00:22:45 +00007274 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7275}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007276
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007277/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007278/// Key-Value Observing (KVO).
7279static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7280 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007281 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007282 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007283 ResultBuilder &Results) {
7284 IdentifierInfo *PropName = Property->getIdentifier();
7285 if (!PropName || PropName->getLength() == 0)
7286 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007287
Douglas Gregor75acd922011-09-27 23:30:47 +00007288 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7289
Douglas Gregor669a25a2011-02-17 00:22:45 +00007290 // Builder that will create each code completion.
7291 typedef CodeCompletionResult Result;
7292 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007293 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007294
Douglas Gregor669a25a2011-02-17 00:22:45 +00007295 // The selector table.
7296 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007297
Douglas Gregor669a25a2011-02-17 00:22:45 +00007298 // The property name, copied into the code completion allocation region
7299 // on demand.
7300 struct KeyHolder {
7301 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007302 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007303 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007304
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007305 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007306 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007307
Douglas Gregor669a25a2011-02-17 00:22:45 +00007308 operator const char *() {
7309 if (CopiedKey)
7310 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007311
Douglas Gregor669a25a2011-02-17 00:22:45 +00007312 return CopiedKey = Allocator.CopyString(Key);
7313 }
7314 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007315
Douglas Gregor669a25a2011-02-17 00:22:45 +00007316 // The uppercased name of the property name.
7317 std::string UpperKey = PropName->getName();
7318 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007319 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007320
Fangrui Song050229d2018-11-24 00:14:31 +00007321 bool ReturnTypeMatchesProperty =
7322 ReturnType.isNull() ||
7323 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7324 Property->getType());
7325 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007326
Douglas Gregor669a25a2011-02-17 00:22:45 +00007327 // Add the normal accessor -(type)key.
7328 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007329 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007330 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7331 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007332 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7333 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007334
Douglas Gregor669a25a2011-02-17 00:22:45 +00007335 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007336 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007337 CXCursor_ObjCInstanceMethodDecl));
7338 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007339
Douglas Gregor669a25a2011-02-17 00:22:45 +00007340 // If we have an integral or boolean property (or the user has provided
7341 // an integral or boolean return type), add the accessor -(type)isKey.
7342 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007343 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007344 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007345 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7346 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007347 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007348 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007349 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7350 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007351 if (ReturnType.isNull()) {
7352 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7353 Builder.AddTextChunk("BOOL");
7354 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7355 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007356
Fangrui Song050229d2018-11-24 00:14:31 +00007357 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007358 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007359 CXCursor_ObjCInstanceMethodDecl));
7360 }
7361 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007362
Douglas Gregor669a25a2011-02-17 00:22:45 +00007363 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007364 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007365 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007366 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007367 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007368 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007369 if (ReturnType.isNull()) {
7370 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7371 Builder.AddTextChunk("void");
7372 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7373 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007374
Fangrui Song050229d2018-11-24 00:14:31 +00007375 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007376 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007377 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7378 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007379 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007380 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007381 CXCursor_ObjCInstanceMethodDecl));
7382 }
7383 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007384
Douglas Gregor669a25a2011-02-17 00:22:45 +00007385 // Indexed and unordered accessors
7386 unsigned IndexedGetterPriority = CCP_CodePattern;
7387 unsigned IndexedSetterPriority = CCP_CodePattern;
7388 unsigned UnorderedGetterPriority = CCP_CodePattern;
7389 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007390 if (const auto *ObjCPointer =
7391 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007392 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7393 // If this interface type is not provably derived from a known
7394 // collection, penalize the corresponding completions.
7395 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007396 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007397 if (!InheritsFromClassNamed(IFace, "NSArray"))
7398 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7399 }
7400
7401 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007402 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007403 if (!InheritsFromClassNamed(IFace, "NSSet"))
7404 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7405 }
7406 }
7407 } else {
7408 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7409 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7410 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7411 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7412 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007413
Douglas Gregor669a25a2011-02-17 00:22:45 +00007414 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007415 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007416 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007417 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007418 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007419 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7420 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007421 if (ReturnType.isNull()) {
7422 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7423 Builder.AddTextChunk("NSUInteger");
7424 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7425 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007426
Fangrui Song050229d2018-11-24 00:14:31 +00007427 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7428 Results.AddResult(
7429 Result(Builder.TakeString(),
7430 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7431 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007432 }
7433 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007434
Douglas Gregor669a25a2011-02-17 00:22:45 +00007435 // Indexed getters
7436 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7437 if (IsInstanceMethod &&
7438 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007439 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007440 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007441 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007442 if (ReturnType.isNull()) {
7443 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7444 Builder.AddTextChunk("id");
7445 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7446 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007447
Douglas Gregor669a25a2011-02-17 00:22:45 +00007448 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7449 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7450 Builder.AddTextChunk("NSUInteger");
7451 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7452 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007453 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007454 CXCursor_ObjCInstanceMethodDecl));
7455 }
7456 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007457
Douglas Gregor669a25a2011-02-17 00:22:45 +00007458 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7459 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007460 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007461 (ReturnType->isObjCObjectPointerType() &&
7462 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007463 ReturnType->getAs<ObjCObjectPointerType>()
7464 ->getInterfaceDecl()
7465 ->getName() == "NSArray"))) {
7466 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007467 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007468 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007469 if (ReturnType.isNull()) {
7470 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7471 Builder.AddTextChunk("NSArray *");
7472 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7473 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007474
Douglas Gregor669a25a2011-02-17 00:22:45 +00007475 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7476 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7477 Builder.AddTextChunk("NSIndexSet *");
7478 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7479 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007480 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007481 CXCursor_ObjCInstanceMethodDecl));
7482 }
7483 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007484
Douglas Gregor669a25a2011-02-17 00:22:45 +00007485 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7486 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007487 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007488 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7489 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007490
David Blaikie82e95a32014-11-19 07:49:47 +00007491 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007492 if (ReturnType.isNull()) {
7493 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7494 Builder.AddTextChunk("void");
7495 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7496 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007497
Douglas Gregor669a25a2011-02-17 00:22:45 +00007498 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7499 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7500 Builder.AddPlaceholderChunk("object-type");
7501 Builder.AddTextChunk(" **");
7502 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7503 Builder.AddTextChunk("buffer");
7504 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7505 Builder.AddTypedTextChunk("range:");
7506 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7507 Builder.AddTextChunk("NSRange");
7508 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7509 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007510 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007511 CXCursor_ObjCInstanceMethodDecl));
7512 }
7513 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007514
Douglas Gregor669a25a2011-02-17 00:22:45 +00007515 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007516
Douglas Gregor669a25a2011-02-17 00:22:45 +00007517 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7518 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007519 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007520 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7521 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007522
David Blaikie82e95a32014-11-19 07:49:47 +00007523 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007524 if (ReturnType.isNull()) {
7525 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7526 Builder.AddTextChunk("void");
7527 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7528 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007529
Douglas Gregor669a25a2011-02-17 00:22:45 +00007530 Builder.AddTypedTextChunk("insertObject:");
7531 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7532 Builder.AddPlaceholderChunk("object-type");
7533 Builder.AddTextChunk(" *");
7534 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7535 Builder.AddTextChunk("object");
7536 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7537 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7538 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7539 Builder.AddPlaceholderChunk("NSUInteger");
7540 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7541 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007542 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007543 CXCursor_ObjCInstanceMethodDecl));
7544 }
7545 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007546
Douglas Gregor669a25a2011-02-17 00:22:45 +00007547 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7548 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007549 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007550 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7551 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007552
David Blaikie82e95a32014-11-19 07:49:47 +00007553 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007554 if (ReturnType.isNull()) {
7555 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7556 Builder.AddTextChunk("void");
7557 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7558 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007559
Douglas Gregor669a25a2011-02-17 00:22:45 +00007560 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7561 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7562 Builder.AddTextChunk("NSArray *");
7563 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7564 Builder.AddTextChunk("array");
7565 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7566 Builder.AddTypedTextChunk("atIndexes:");
7567 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7568 Builder.AddPlaceholderChunk("NSIndexSet *");
7569 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7570 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007571 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 CXCursor_ObjCInstanceMethodDecl));
7573 }
7574 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007575
Douglas Gregor669a25a2011-02-17 00:22:45 +00007576 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7577 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007578 std::string SelectorName =
7579 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007580 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007581 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007582 if (ReturnType.isNull()) {
7583 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7584 Builder.AddTextChunk("void");
7585 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7586 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007587
Douglas Gregor669a25a2011-02-17 00:22:45 +00007588 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7589 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7590 Builder.AddTextChunk("NSUInteger");
7591 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7592 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007593 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007594 CXCursor_ObjCInstanceMethodDecl));
7595 }
7596 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007597
Douglas Gregor669a25a2011-02-17 00:22:45 +00007598 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7599 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007600 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007601 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007602 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007603 if (ReturnType.isNull()) {
7604 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7605 Builder.AddTextChunk("void");
7606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7607 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007608
Douglas Gregor669a25a2011-02-17 00:22:45 +00007609 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7610 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7611 Builder.AddTextChunk("NSIndexSet *");
7612 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7613 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007614 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007615 CXCursor_ObjCInstanceMethodDecl));
7616 }
7617 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007618
Douglas Gregor669a25a2011-02-17 00:22:45 +00007619 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7620 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007621 std::string SelectorName =
7622 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7623 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7624 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007625
David Blaikie82e95a32014-11-19 07:49:47 +00007626 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007627 if (ReturnType.isNull()) {
7628 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7629 Builder.AddTextChunk("void");
7630 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7631 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007632
Douglas Gregor669a25a2011-02-17 00:22:45 +00007633 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7634 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7635 Builder.AddPlaceholderChunk("NSUInteger");
7636 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7637 Builder.AddTextChunk("index");
7638 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7639 Builder.AddTypedTextChunk("withObject:");
7640 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7641 Builder.AddTextChunk("id");
7642 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7643 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007644 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007645 CXCursor_ObjCInstanceMethodDecl));
7646 }
7647 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007648
Douglas Gregor669a25a2011-02-17 00:22:45 +00007649 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7650 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007651 std::string SelectorName1 =
7652 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007653 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007654 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7655 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007656
David Blaikie82e95a32014-11-19 07:49:47 +00007657 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007658 if (ReturnType.isNull()) {
7659 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7660 Builder.AddTextChunk("void");
7661 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7662 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007663
Douglas Gregor669a25a2011-02-17 00:22:45 +00007664 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7665 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7666 Builder.AddPlaceholderChunk("NSIndexSet *");
7667 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7668 Builder.AddTextChunk("indexes");
7669 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7670 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7671 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7672 Builder.AddTextChunk("NSArray *");
7673 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7674 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007675 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007676 CXCursor_ObjCInstanceMethodDecl));
7677 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007678 }
7679
Douglas Gregor669a25a2011-02-17 00:22:45 +00007680 // Unordered getters
7681 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007682 if (IsInstanceMethod &&
7683 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007684 (ReturnType->isObjCObjectPointerType() &&
7685 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007686 ReturnType->getAs<ObjCObjectPointerType>()
7687 ->getInterfaceDecl()
7688 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007689 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007690 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007691 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7692 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007693 if (ReturnType.isNull()) {
7694 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7695 Builder.AddTextChunk("NSEnumerator *");
7696 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7697 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007698
Douglas Gregor669a25a2011-02-17 00:22:45 +00007699 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007700 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007701 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007702 }
7703 }
7704
7705 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007706 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007707 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007708 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007709 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007710 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007711 if (ReturnType.isNull()) {
7712 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7713 Builder.AddPlaceholderChunk("object-type");
7714 Builder.AddTextChunk(" *");
7715 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7716 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007717
Douglas Gregor669a25a2011-02-17 00:22:45 +00007718 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7719 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7720 if (ReturnType.isNull()) {
7721 Builder.AddPlaceholderChunk("object-type");
7722 Builder.AddTextChunk(" *");
7723 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007724 Builder.AddTextChunk(GetCompletionTypeString(
7725 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007726 }
7727 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7728 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007729 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007730 CXCursor_ObjCInstanceMethodDecl));
7731 }
7732 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007733
Douglas Gregor669a25a2011-02-17 00:22:45 +00007734 // Mutable unordered accessors
7735 // - (void)addKeyObject:(type *)object
7736 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007737 std::string SelectorName =
7738 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007739 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007740 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007741 if (ReturnType.isNull()) {
7742 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7743 Builder.AddTextChunk("void");
7744 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7745 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007746
Douglas Gregor669a25a2011-02-17 00:22:45 +00007747 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7748 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7749 Builder.AddPlaceholderChunk("object-type");
7750 Builder.AddTextChunk(" *");
7751 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7752 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007753 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007754 CXCursor_ObjCInstanceMethodDecl));
7755 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007756 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007757
7758 // - (void)addKey:(NSSet *)objects
7759 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007760 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007761 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007762 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007763 if (ReturnType.isNull()) {
7764 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7765 Builder.AddTextChunk("void");
7766 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7767 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007768
Douglas Gregor669a25a2011-02-17 00:22:45 +00007769 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7770 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7771 Builder.AddTextChunk("NSSet *");
7772 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7773 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007774 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007775 CXCursor_ObjCInstanceMethodDecl));
7776 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007777 }
7778
Douglas Gregor669a25a2011-02-17 00:22:45 +00007779 // - (void)removeKeyObject:(type *)object
7780 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007781 std::string SelectorName =
7782 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007783 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007784 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007785 if (ReturnType.isNull()) {
7786 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7787 Builder.AddTextChunk("void");
7788 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7789 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007790
Douglas Gregor669a25a2011-02-17 00:22:45 +00007791 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7792 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7793 Builder.AddPlaceholderChunk("object-type");
7794 Builder.AddTextChunk(" *");
7795 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7796 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007797 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007798 CXCursor_ObjCInstanceMethodDecl));
7799 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007800 }
7801
Douglas Gregor669a25a2011-02-17 00:22:45 +00007802 // - (void)removeKey:(NSSet *)objects
7803 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007804 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007805 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007806 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007807 if (ReturnType.isNull()) {
7808 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7809 Builder.AddTextChunk("void");
7810 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7811 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007812
Douglas Gregor669a25a2011-02-17 00:22:45 +00007813 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7814 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7815 Builder.AddTextChunk("NSSet *");
7816 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7817 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007818 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007819 CXCursor_ObjCInstanceMethodDecl));
7820 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007821 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007822
7823 // - (void)intersectKey:(NSSet *)objects
7824 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007825 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007826 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007827 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007828 if (ReturnType.isNull()) {
7829 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7830 Builder.AddTextChunk("void");
7831 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7832 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007833
Douglas Gregor669a25a2011-02-17 00:22:45 +00007834 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7835 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7836 Builder.AddTextChunk("NSSet *");
7837 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7838 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007839 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007840 CXCursor_ObjCInstanceMethodDecl));
7841 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007842 }
7843
Douglas Gregor669a25a2011-02-17 00:22:45 +00007844 // Key-Value Observing
7845 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007846 if (!IsInstanceMethod &&
7847 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007848 (ReturnType->isObjCObjectPointerType() &&
7849 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007850 ReturnType->getAs<ObjCObjectPointerType>()
7851 ->getInterfaceDecl()
7852 ->getName() == "NSSet"))) {
7853 std::string SelectorName =
7854 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007855 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007856 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7857 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007858 if (ReturnType.isNull()) {
7859 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007860 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007861 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7862 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007863
Douglas Gregor669a25a2011-02-17 00:22:45 +00007864 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007865 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007866 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00007867 }
7868 }
7869
7870 // + (BOOL)automaticallyNotifiesObserversForKey
7871 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00007872 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007873 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007874 std::string SelectorName =
7875 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007876 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007877 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7878 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007879 if (ReturnType.isNull()) {
7880 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7881 Builder.AddTextChunk("BOOL");
7882 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7883 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007884
Douglas Gregor857bcda2011-06-02 04:02:27 +00007885 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007886 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007887 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007888 }
7889 }
7890}
7891
Alex Lorenzb8740422017-10-24 16:39:37 +00007892void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007893 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007894 // Determine the return type of the method we're declaring, if
7895 // provided.
7896 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007897 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007898 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007899 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7900 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007901 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007902 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007903 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007904 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007905 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007906 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7907 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007908 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00007909 } else if (ObjCCategoryImplDecl *CatImpl =
7910 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007911 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007912 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007913 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007914 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007915 }
7916
7917 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007918 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007919 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007920 }
7921
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007922 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007923 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00007924 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007925 return;
7926 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007927
Douglas Gregor636a61e2010-04-07 00:21:17 +00007928 // Find all of the methods that we could declare/implement here.
7929 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00007930 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
7931 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007932
Douglas Gregor636a61e2010-04-07 00:21:17 +00007933 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007934 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007935 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007936 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007937 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007938 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007939 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007940 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007941 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007942 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007943 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007944 CodeCompletionBuilder Builder(Results.getAllocator(),
7945 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007946
7947 // Add the '-'/'+' prefix if it wasn't provided yet.
7948 if (!IsInstanceMethod) {
7949 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7950 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7951 }
7952
Douglas Gregor636a61e2010-04-07 00:21:17 +00007953 // If the result type was not already provided, add it to the
7954 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007955 if (ReturnType.isNull()) {
7956 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7957 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00007958 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
7959 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007960 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007961
7962 Selector Sel = Method->getSelector();
7963
7964 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00007965 Builder.AddTypedTextChunk(
7966 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007967
7968 // Add parameters to the pattern.
7969 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007970 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007971 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007972 P != PEnd; (void)++P, ++I) {
7973 // Add the part of the selector name.
7974 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007975 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007976 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007977 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7978 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00007979 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007980 } else
7981 break;
7982
7983 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007984 QualType ParamType;
7985 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7986 ParamType = (*P)->getType();
7987 else
7988 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00007989 ParamType = ParamType.substObjCTypeArgs(
7990 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007991 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00007992 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
7993 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007994
Douglas Gregor636a61e2010-04-07 00:21:17 +00007995 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00007996 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007997 }
7998
7999 if (Method->isVariadic()) {
8000 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008001 Builder.AddChunk(CodeCompletionString::CK_Comma);
8002 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008003 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008004
Douglas Gregord37c59d2010-05-28 00:57:46 +00008005 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008006 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008007 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8008 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8009 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008010 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008011 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008012 Builder.AddTextChunk("return");
8013 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8014 Builder.AddPlaceholderChunk("expression");
8015 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008016 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008017 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008018
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008019 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8020 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008021 }
8022
Douglas Gregor416b5752010-08-25 01:08:01 +00008023 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008024 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008025 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008026 setInBaseClass(R);
8027 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008028 }
8029
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008030 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008031 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008032 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008033 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008034 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008035
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008036 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008037 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008038 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008039 M != MEnd; ++M)
8040 KnownSelectors.insert(M->first);
8041
Douglas Gregor669a25a2011-02-17 00:22:45 +00008042 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8043 if (!IFace)
8044 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8045 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008046
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008047 if (IFace)
8048 for (auto *Cat : IFace->visible_categories())
8049 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008050
8051 if (IsInstanceMethod) {
8052 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8053 for (auto *P : Containers[I]->instance_properties())
8054 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8055 KnownSelectors, Results);
8056 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008057 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008058
Douglas Gregor636a61e2010-04-07 00:21:17 +00008059 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008060
8061 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8062 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008063}
Douglas Gregor95887f92010-07-08 23:20:03 +00008064
Fangrui Song050229d2018-11-24 00:14:31 +00008065void Sema::CodeCompleteObjCMethodDeclSelector(
8066 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8067 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008068 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008069 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008070 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008071 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8072 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008073 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008074 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008075 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008076
8077 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008078 }
8079 }
8080
8081 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008082 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008083 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008084 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008085 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008086
Douglas Gregor95887f92010-07-08 23:20:03 +00008087 if (ReturnTy)
8088 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008089
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008090 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008091 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8092 MEnd = MethodPool.end();
8093 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008094 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8095 : &M->second.second;
8096 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008097 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008098 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008099
Douglas Gregor45879692010-07-08 23:37:41 +00008100 if (AtParameterName) {
8101 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008102 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008103 if (NumSelIdents &&
8104 NumSelIdents <= MethList->getMethod()->param_size()) {
8105 ParmVarDecl *Param =
8106 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008107 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008108 CodeCompletionBuilder Builder(Results.getAllocator(),
8109 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008110 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008111 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008112 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008113 }
8114 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008115
Douglas Gregor45879692010-07-08 23:37:41 +00008116 continue;
8117 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008118
Nico Weber2e0c8f72014-12-27 03:58:08 +00008119 Result R(MethList->getMethod(),
8120 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008121 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008122 R.AllParametersAreInformative = false;
8123 R.DeclaringEntity = true;
8124 Results.MaybeAddResult(R, CurContext);
8125 }
8126 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008127
Douglas Gregor95887f92010-07-08 23:20:03 +00008128 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008129
8130 if (!AtParameterName && !SelIdents.empty() &&
8131 SelIdents.front()->getName().startswith("init")) {
8132 for (const auto &M : PP.macros()) {
8133 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8134 continue;
8135 Results.EnterNewScope();
8136 CodeCompletionBuilder Builder(Results.getAllocator(),
8137 Results.getCodeCompletionTUInfo());
8138 Builder.AddTypedTextChunk(
8139 Builder.getAllocator().CopyString(M.first->getName()));
8140 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8141 CXCursor_MacroDefinition));
8142 Results.ExitScope();
8143 }
8144 }
8145
Eric Liuf5ba09f2018-07-04 10:01:18 +00008146 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8147 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008148}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008149
Douglas Gregorec00a262010-08-24 22:20:20 +00008150void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008151 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008152 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008153 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008154 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008155
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008156 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008157 CodeCompletionBuilder Builder(Results.getAllocator(),
8158 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008159 Builder.AddTypedTextChunk("if");
8160 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8161 Builder.AddPlaceholderChunk("condition");
8162 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008163
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008164 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008165 Builder.AddTypedTextChunk("ifdef");
8166 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8167 Builder.AddPlaceholderChunk("macro");
8168 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008169
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008170 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008171 Builder.AddTypedTextChunk("ifndef");
8172 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8173 Builder.AddPlaceholderChunk("macro");
8174 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008175
8176 if (InConditional) {
8177 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008178 Builder.AddTypedTextChunk("elif");
8179 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8180 Builder.AddPlaceholderChunk("condition");
8181 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008182
8183 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008184 Builder.AddTypedTextChunk("else");
8185 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008186
8187 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008188 Builder.AddTypedTextChunk("endif");
8189 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008190 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008191
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008192 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008193 Builder.AddTypedTextChunk("include");
8194 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8195 Builder.AddTextChunk("\"");
8196 Builder.AddPlaceholderChunk("header");
8197 Builder.AddTextChunk("\"");
8198 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008199
8200 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008201 Builder.AddTypedTextChunk("include");
8202 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8203 Builder.AddTextChunk("<");
8204 Builder.AddPlaceholderChunk("header");
8205 Builder.AddTextChunk(">");
8206 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008207
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008208 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008209 Builder.AddTypedTextChunk("define");
8210 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8211 Builder.AddPlaceholderChunk("macro");
8212 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008213
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008214 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008215 Builder.AddTypedTextChunk("define");
8216 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8217 Builder.AddPlaceholderChunk("macro");
8218 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8219 Builder.AddPlaceholderChunk("args");
8220 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8221 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008222
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008223 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008224 Builder.AddTypedTextChunk("undef");
8225 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8226 Builder.AddPlaceholderChunk("macro");
8227 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008228
8229 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008230 Builder.AddTypedTextChunk("line");
8231 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8232 Builder.AddPlaceholderChunk("number");
8233 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008234
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008235 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008236 Builder.AddTypedTextChunk("line");
8237 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8238 Builder.AddPlaceholderChunk("number");
8239 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8240 Builder.AddTextChunk("\"");
8241 Builder.AddPlaceholderChunk("filename");
8242 Builder.AddTextChunk("\"");
8243 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008244
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008245 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008246 Builder.AddTypedTextChunk("error");
8247 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8248 Builder.AddPlaceholderChunk("message");
8249 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008250
8251 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008252 Builder.AddTypedTextChunk("pragma");
8253 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8254 Builder.AddPlaceholderChunk("arguments");
8255 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008256
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008257 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008258 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008259 Builder.AddTypedTextChunk("import");
8260 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8261 Builder.AddTextChunk("\"");
8262 Builder.AddPlaceholderChunk("header");
8263 Builder.AddTextChunk("\"");
8264 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008265
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008266 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008267 Builder.AddTypedTextChunk("import");
8268 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8269 Builder.AddTextChunk("<");
8270 Builder.AddPlaceholderChunk("header");
8271 Builder.AddTextChunk(">");
8272 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008273 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008274
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008275 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008276 Builder.AddTypedTextChunk("include_next");
8277 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8278 Builder.AddTextChunk("\"");
8279 Builder.AddPlaceholderChunk("header");
8280 Builder.AddTextChunk("\"");
8281 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008282
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008283 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008284 Builder.AddTypedTextChunk("include_next");
8285 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8286 Builder.AddTextChunk("<");
8287 Builder.AddPlaceholderChunk("header");
8288 Builder.AddTextChunk(">");
8289 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008290
8291 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008292 Builder.AddTypedTextChunk("warning");
8293 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8294 Builder.AddPlaceholderChunk("message");
8295 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008296
8297 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8298 // completions for them. And __include_macros is a Clang-internal extension
8299 // that we don't want to encourage anyone to use.
8300
8301 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8302 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008303
8304 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008305 Results.data(), Results.size());
8306}
8307
8308void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008309 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8310 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008311}
8312
Douglas Gregorec00a262010-08-24 22:20:20 +00008313void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008314 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008315 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008316 IsDefinition ? CodeCompletionContext::CCC_MacroName
8317 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008318 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008319 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008320 CodeCompletionBuilder Builder(Results.getAllocator(),
8321 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008322 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008323 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008324 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008325 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008326 Builder.AddTypedTextChunk(
8327 Builder.getAllocator().CopyString(M->first->getName()));
8328 Results.AddResult(CodeCompletionResult(
8329 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008330 }
8331 Results.ExitScope();
8332 } else if (IsDefinition) {
8333 // FIXME: Can we detect when the user just wrote an include guard above?
8334 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008335
Douglas Gregor0ac41382010-09-23 23:01:17 +00008336 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008337 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008338}
8339
Douglas Gregorec00a262010-08-24 22:20:20 +00008340void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008341 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008342 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008343 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008344
Douglas Gregorec00a262010-08-24 22:20:20 +00008345 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008346 AddMacroResults(PP, Results,
8347 CodeCompleter ? CodeCompleter->loadExternal() : false,
8348 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008349
Fangrui Song050229d2018-11-24 00:14:31 +00008350 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008351 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008352 CodeCompletionBuilder Builder(Results.getAllocator(),
8353 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008354 Builder.AddTypedTextChunk("defined");
8355 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8356 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8357 Builder.AddPlaceholderChunk("macro");
8358 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8359 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008360 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008361
8362 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8363 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008364}
8365
8366void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8367 IdentifierInfo *Macro,
8368 MacroInfo *MacroInfo,
8369 unsigned Argument) {
8370 // FIXME: In the future, we could provide "overload" results, much like we
8371 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008372
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008373 // Now just ignore this. There will be another code-completion callback
8374 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008375}
8376
Sam McCall3d8051a2018-09-18 08:40:41 +00008377// This handles completion inside an #include filename, e.g. #include <foo/ba
8378// We look for the directory "foo" under each directory on the include path,
8379// list its files, and reassemble the appropriate #include.
8380void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8381 // RelDir should use /, but unescaped \ is possible on windows!
8382 // Our completions will normalize to / for simplicity, this case is rare.
8383 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8384 // We need the native slashes for the actual file system interactions.
8385 SmallString<128> NativeRelDir = StringRef(RelDir);
8386 llvm::sys::path::native(NativeRelDir);
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008387 llvm::vfs::FileSystem &FS =
8388 getSourceManager().getFileManager().getVirtualFileSystem();
Sam McCall3d8051a2018-09-18 08:40:41 +00008389
8390 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8391 CodeCompleter->getCodeCompletionTUInfo(),
8392 CodeCompletionContext::CCC_IncludedFile);
8393 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8394
8395 // Helper: adds one file or directory completion result.
8396 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8397 SmallString<64> TypedChunk = Filename;
8398 // Directory completion is up to the slash, e.g. <sys/
8399 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8400 auto R = SeenResults.insert(TypedChunk);
8401 if (R.second) { // New completion
8402 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8403 *R.first = InternedTyped; // Avoid dangling StringRef.
8404 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8405 CodeCompleter->getCodeCompletionTUInfo());
8406 Builder.AddTypedTextChunk(InternedTyped);
8407 // The result is a "Pattern", which is pretty opaque.
8408 // We may want to include the real filename to allow smart ranking.
8409 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8410 }
8411 };
8412
8413 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008414 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8415 bool IsSystem,
8416 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008417 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008418 if (!NativeRelDir.empty()) {
8419 if (LookupType == DirectoryLookup::LT_Framework) {
8420 // For a framework dir, #include <Foo/Bar/> actually maps to
8421 // a path of Foo.framework/Headers/Bar/.
8422 auto Begin = llvm::sys::path::begin(NativeRelDir);
8423 auto End = llvm::sys::path::end(NativeRelDir);
8424
8425 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8426 llvm::sys::path::append(Dir, ++Begin, End);
8427 } else {
8428 llvm::sys::path::append(Dir, NativeRelDir);
8429 }
8430 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008431
8432 std::error_code EC;
8433 unsigned Count = 0;
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008434 for (auto It = FS.dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008435 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008436 if (++Count == 2500) // If we happen to hit a huge directory,
8437 break; // bail out early so we're not too slow.
8438 StringRef Filename = llvm::sys::path::filename(It->path());
8439 switch (It->type()) {
8440 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008441 // All entries in a framework directory must have a ".framework" suffix,
8442 // but the suffix does not appear in the source code's include/import.
8443 if (LookupType == DirectoryLookup::LT_Framework &&
8444 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8445 break;
8446
Sam McCall3d8051a2018-09-18 08:40:41 +00008447 AddCompletion(Filename, /*IsDirectory=*/true);
8448 break;
8449 case llvm::sys::fs::file_type::regular_file:
8450 // Only files that really look like headers. (Except in system dirs).
8451 if (!IsSystem) {
8452 // Header extensions from Types.def, which we can't depend on here.
8453 if (!(Filename.endswith_lower(".h") ||
8454 Filename.endswith_lower(".hh") ||
8455 Filename.endswith_lower(".hpp") ||
8456 Filename.endswith_lower(".inc")))
8457 break;
8458 }
8459 AddCompletion(Filename, /*IsDirectory=*/false);
8460 break;
8461 default:
8462 break;
8463 }
8464 }
8465 };
8466
8467 // Helper: adds results relative to IncludeDir, if possible.
8468 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8469 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008470 switch (IncludeDir.getLookupType()) {
8471 case DirectoryLookup::LT_HeaderMap:
8472 // header maps are not (currently) enumerable.
8473 break;
8474 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008475 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8476 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008477 break;
8478 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008479 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8480 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008481 break;
8482 }
8483 };
8484
8485 // Finally with all our helpers, we can scan the include path.
8486 // Do this in standard order so deduplication keeps the right file.
8487 // (In case we decide to add more details to the results later).
8488 const auto &S = PP.getHeaderSearchInfo();
8489 using llvm::make_range;
8490 if (!Angled) {
8491 // The current directory is on the include path for "quoted" includes.
8492 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8493 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008494 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8495 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008496 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8497 AddFilesFromDirLookup(D, false);
8498 }
8499 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008500 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008501 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8502 AddFilesFromDirLookup(D, true);
8503
8504 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8505 Results.data(), Results.size());
8506}
8507
Douglas Gregor11583702010-08-25 17:04:25 +00008508void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008509 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008510 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8511 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008512}
8513
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008514void Sema::CodeCompleteAvailabilityPlatformName() {
8515 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8516 CodeCompleter->getCodeCompletionTUInfo(),
8517 CodeCompletionContext::CCC_Other);
8518 Results.EnterNewScope();
8519 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8520 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8521 Results.AddResult(CodeCompletionResult(Platform));
8522 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8523 Twine(Platform) + "ApplicationExtension")));
8524 }
8525 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008526 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8527 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008528}
8529
Fangrui Song050229d2018-11-24 00:14:31 +00008530void Sema::GatherGlobalCodeCompletions(
8531 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8532 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008533 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8534 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008535 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008536 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008537 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008538 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8539 Consumer,
8540 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008541 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008542
Douglas Gregorb14904c2010-08-13 22:48:40 +00008543 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008544 AddMacroResults(PP, Builder,
8545 CodeCompleter ? CodeCompleter->loadExternal() : false,
8546 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008547
Douglas Gregorb14904c2010-08-13 22:48:40 +00008548 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008549 Results.insert(Results.end(), Builder.data(),
8550 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008551}