blob: e6c0b68b8d5fd0215b317697e3cd01b1075356f7 [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");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001926 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001927 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001928
1929 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001930 Builder.AddTypedTextChunk("using");
1931 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1932 Builder.AddTextChunk("namespace");
1933 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1934 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001935 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001936 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001937
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001938 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001939 Builder.AddTypedTextChunk("asm");
1940 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1941 Builder.AddPlaceholderChunk("string-literal");
1942 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1943 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001944
Douglas Gregorf4c33342010-05-28 00:22:41 +00001945 if (Results.includeCodePatterns()) {
1946 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001947 Builder.AddTypedTextChunk("template");
1948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1949 Builder.AddPlaceholderChunk("declaration");
1950 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001951 } else {
1952 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001953 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001954 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001955
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001956 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001957 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001958
Douglas Gregorf4c33342010-05-28 00:22:41 +00001959 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001960 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001961
John McCallfaf5fb42010-08-26 23:41:50 +00001962 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001963 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001964 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001965 Builder.AddTypedTextChunk("using");
1966 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1967 Builder.AddPlaceholderChunk("qualifier");
1968 Builder.AddTextChunk("::");
1969 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001970 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001971 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001972
Douglas Gregorf4c33342010-05-28 00:22:41 +00001973 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001974 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001975 Builder.AddTypedTextChunk("using");
1976 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1977 Builder.AddTextChunk("typename");
1978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1979 Builder.AddPlaceholderChunk("qualifier");
1980 Builder.AddTextChunk("::");
1981 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00001982 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001983 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001984 }
1985
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001986 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1987
John McCallfaf5fb42010-08-26 23:41:50 +00001988 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001989 AddTypedefResult(Results);
1990
Erik Verbruggen6524c052017-10-24 13:46:58 +00001991 bool IsNotInheritanceScope =
1992 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001993 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001994 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001995 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001996 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001997 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001998
1999 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002000 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002001 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002002 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002003 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002004
2005 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002006 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002007 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002008 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002009 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002010
2011 // FIXME: This adds override results only if we are at the first word of
2012 // the declaration/definition. Also call this from other sides to have
2013 // more use-cases.
2014 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
2015 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002016 }
2017 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002018 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002019
John McCallfaf5fb42010-08-26 23:41:50 +00002020 case Sema::PCC_Template:
2021 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002022 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002023 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002024 Builder.AddTypedTextChunk("template");
2025 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2026 Builder.AddPlaceholderChunk("parameters");
2027 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2028 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002029 } else {
2030 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002031 }
2032
David Blaikiebbafb8a2012-03-11 07:00:24 +00002033 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2034 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002035 break;
2036
John McCallfaf5fb42010-08-26 23:41:50 +00002037 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002038 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2039 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2040 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002041 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002042
John McCallfaf5fb42010-08-26 23:41:50 +00002043 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002044 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2045 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2046 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002047 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002048
John McCallfaf5fb42010-08-26 23:41:50 +00002049 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002050 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002051 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002052
John McCallfaf5fb42010-08-26 23:41:50 +00002053 case Sema::PCC_RecoveryInFunction:
2054 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002055 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002056
David Blaikiebbafb8a2012-03-11 07:00:24 +00002057 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2058 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002059 Builder.AddTypedTextChunk("try");
2060 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2061 Builder.AddPlaceholderChunk("statements");
2062 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2063 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2064 Builder.AddTextChunk("catch");
2065 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2066 Builder.AddPlaceholderChunk("declaration");
2067 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2068 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2069 Builder.AddPlaceholderChunk("statements");
2070 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2071 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2072 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002073 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002074 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002075 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002076
Douglas Gregorf64acca2010-05-25 21:41:55 +00002077 if (Results.includeCodePatterns()) {
2078 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002079 Builder.AddTypedTextChunk("if");
2080 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002081 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002082 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002083 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002084 Builder.AddPlaceholderChunk("expression");
2085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2086 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2087 Builder.AddPlaceholderChunk("statements");
2088 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2089 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2090 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002091
Douglas Gregorf64acca2010-05-25 21:41:55 +00002092 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002093 Builder.AddTypedTextChunk("switch");
2094 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002095 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002096 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002097 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002098 Builder.AddPlaceholderChunk("expression");
2099 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2100 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2101 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2102 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2103 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002104 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002105
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002106 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002107 if (SemaRef.getCurFunction() &&
2108 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002109 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002110 Builder.AddTypedTextChunk("case");
2111 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2112 Builder.AddPlaceholderChunk("expression");
2113 Builder.AddChunk(CodeCompletionString::CK_Colon);
2114 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002115
2116 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002117 Builder.AddTypedTextChunk("default");
2118 Builder.AddChunk(CodeCompletionString::CK_Colon);
2119 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002120 }
2121
Douglas Gregorf64acca2010-05-25 21:41:55 +00002122 if (Results.includeCodePatterns()) {
2123 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002124 Builder.AddTypedTextChunk("while");
2125 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002126 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002127 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002128 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002129 Builder.AddPlaceholderChunk("expression");
2130 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2131 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2132 Builder.AddPlaceholderChunk("statements");
2133 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2134 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2135 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002136
2137 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002138 Builder.AddTypedTextChunk("do");
2139 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2140 Builder.AddPlaceholderChunk("statements");
2141 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2142 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2143 Builder.AddTextChunk("while");
2144 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2145 Builder.AddPlaceholderChunk("expression");
2146 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2147 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002148
Douglas Gregorf64acca2010-05-25 21:41:55 +00002149 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002150 Builder.AddTypedTextChunk("for");
2151 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002152 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002153 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002154 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002155 Builder.AddPlaceholderChunk("init-expression");
2156 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2157 Builder.AddPlaceholderChunk("condition");
2158 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2159 Builder.AddPlaceholderChunk("inc-expression");
2160 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2161 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2162 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2163 Builder.AddPlaceholderChunk("statements");
2164 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2165 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2166 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002167 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002168
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002169 if (S->getContinueParent()) {
2170 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002171 Builder.AddTypedTextChunk("continue");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002172 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002173 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002174 }
2175
2176 if (S->getBreakParent()) {
2177 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002178 Builder.AddTypedTextChunk("break");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002179 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002180 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002181 }
2182
2183 // "return expression ;" or "return ;", depending on whether we
2184 // know the function is void or not.
2185 bool isVoid = false;
Fangrui Song050229d2018-11-24 00:14:31 +00002186 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00002187 isVoid = Function->getReturnType()->isVoidType();
Fangrui Song050229d2018-11-24 00:14:31 +00002188 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00002189 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002190 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002191 !SemaRef.getCurBlock()->ReturnType.isNull())
2192 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002193 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00002194 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002195 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2196 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00002197 }
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002198 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002199 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002200
Douglas Gregorf4c33342010-05-28 00:22:41 +00002201 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002202 Builder.AddTypedTextChunk("goto");
2203 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2204 Builder.AddPlaceholderChunk("label");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002205 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002206 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002207
Douglas Gregorf4c33342010-05-28 00:22:41 +00002208 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002209 Builder.AddTypedTextChunk("using");
2210 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2211 Builder.AddTextChunk("namespace");
2212 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2213 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002214 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002215 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002216
2217 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002218 }
Fangrui Song050229d2018-11-24 00:14:31 +00002219 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002220
2221 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002222 case Sema::PCC_ForInit:
2223 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002224 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002225 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002226 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002227
Douglas Gregor5e35d592010-09-14 23:59:36 +00002228 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002229 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002230 CCC == Sema::PCC_ParenthesizedExpression) {
2231 // (__bridge <type>)<expression>
2232 Builder.AddTypedTextChunk("__bridge");
2233 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2234 Builder.AddPlaceholderChunk("type");
2235 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2236 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002237 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002238
2239 // (__bridge_transfer <Objective-C type>)<expression>
2240 Builder.AddTypedTextChunk("__bridge_transfer");
2241 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2242 Builder.AddPlaceholderChunk("Objective-C type");
2243 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2244 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002245 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002246
2247 // (__bridge_retained <CF type>)<expression>
2248 Builder.AddTypedTextChunk("__bridge_retained");
2249 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2250 Builder.AddPlaceholderChunk("CF type");
2251 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2252 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002253 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002254 }
2255 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002256 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002257
John McCallfaf5fb42010-08-26 23:41:50 +00002258 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002259 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002260 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002261 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002262
Douglas Gregore5c79d52011-10-18 21:20:17 +00002263 // true
2264 Builder.AddResultTypeChunk("bool");
2265 Builder.AddTypedTextChunk("true");
2266 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002267
Douglas Gregore5c79d52011-10-18 21:20:17 +00002268 // false
2269 Builder.AddResultTypeChunk("bool");
2270 Builder.AddTypedTextChunk("false");
2271 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002272
David Blaikiebbafb8a2012-03-11 07:00:24 +00002273 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002274 // dynamic_cast < type-id > ( expression )
2275 Builder.AddTypedTextChunk("dynamic_cast");
2276 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2277 Builder.AddPlaceholderChunk("type");
2278 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2279 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2280 Builder.AddPlaceholderChunk("expression");
2281 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002282 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002283 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002284
Douglas Gregorf4c33342010-05-28 00:22:41 +00002285 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002286 Builder.AddTypedTextChunk("static_cast");
2287 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2288 Builder.AddPlaceholderChunk("type");
2289 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2291 Builder.AddPlaceholderChunk("expression");
2292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002293 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002294
Douglas Gregorf4c33342010-05-28 00:22:41 +00002295 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002296 Builder.AddTypedTextChunk("reinterpret_cast");
2297 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2298 Builder.AddPlaceholderChunk("type");
2299 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2300 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2301 Builder.AddPlaceholderChunk("expression");
2302 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002303 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002304
Douglas Gregorf4c33342010-05-28 00:22:41 +00002305 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002306 Builder.AddTypedTextChunk("const_cast");
2307 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2308 Builder.AddPlaceholderChunk("type");
2309 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2310 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2311 Builder.AddPlaceholderChunk("expression");
2312 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002313 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002314
David Blaikiebbafb8a2012-03-11 07:00:24 +00002315 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002316 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002317 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002318 Builder.AddTypedTextChunk("typeid");
2319 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2320 Builder.AddPlaceholderChunk("expression-or-type");
2321 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002322 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002323 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +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_LeftParen);
2330 Builder.AddPlaceholderChunk("expressions");
2331 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002332 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002333
Douglas Gregorf4c33342010-05-28 00:22:41 +00002334 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002335 Builder.AddTypedTextChunk("new");
2336 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2337 Builder.AddPlaceholderChunk("type");
2338 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2339 Builder.AddPlaceholderChunk("size");
2340 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2341 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2342 Builder.AddPlaceholderChunk("expressions");
2343 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002344 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002345
Douglas Gregorf4c33342010-05-28 00:22:41 +00002346 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002347 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002348 Builder.AddTypedTextChunk("delete");
2349 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2350 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002351 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002352
Douglas Gregorf4c33342010-05-28 00:22:41 +00002353 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002354 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002355 Builder.AddTypedTextChunk("delete");
2356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2357 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2358 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2360 Builder.AddPlaceholderChunk("expression");
2361 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002362
David Blaikiebbafb8a2012-03-11 07:00:24 +00002363 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002364 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002365 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002366 Builder.AddTypedTextChunk("throw");
2367 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2368 Builder.AddPlaceholderChunk("expression");
2369 Results.AddResult(Result(Builder.TakeString()));
2370 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002371
Douglas Gregora2db7932010-05-26 22:00:08 +00002372 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002373
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002374 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002375 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002376 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002377 Builder.AddTypedTextChunk("nullptr");
2378 Results.AddResult(Result(Builder.TakeString()));
2379
2380 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002381 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002382 Builder.AddTypedTextChunk("alignof");
2383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2384 Builder.AddPlaceholderChunk("type");
2385 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2386 Results.AddResult(Result(Builder.TakeString()));
2387
2388 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002389 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002390 Builder.AddTypedTextChunk("noexcept");
2391 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2392 Builder.AddPlaceholderChunk("expression");
2393 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2394 Results.AddResult(Result(Builder.TakeString()));
2395
2396 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002397 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002398 Builder.AddTypedTextChunk("sizeof...");
2399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2400 Builder.AddPlaceholderChunk("parameter-pack");
2401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2402 Results.AddResult(Result(Builder.TakeString()));
2403 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002404 }
2405
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002406 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002407 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002408 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2409 // The interface can be NULL.
2410 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002411 if (ID->getSuperClass()) {
2412 std::string SuperType;
2413 SuperType = ID->getSuperClass()->getNameAsString();
2414 if (Method->isInstanceMethod())
2415 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002416
Douglas Gregore5c79d52011-10-18 21:20:17 +00002417 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2418 Builder.AddTypedTextChunk("super");
2419 Results.AddResult(Result(Builder.TakeString()));
2420 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002421 }
2422
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002423 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002424 }
2425
Jordan Rose58d54722012-06-30 21:33:57 +00002426 if (SemaRef.getLangOpts().C11) {
2427 // _Alignof
2428 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002429 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002430 Builder.AddTypedTextChunk("alignof");
2431 else
2432 Builder.AddTypedTextChunk("_Alignof");
2433 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2434 Builder.AddPlaceholderChunk("type");
2435 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2436 Results.AddResult(Result(Builder.TakeString()));
2437 }
2438
Douglas Gregorf4c33342010-05-28 00:22:41 +00002439 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002440 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002441 Builder.AddTypedTextChunk("sizeof");
2442 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2443 Builder.AddPlaceholderChunk("expression-or-type");
2444 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2445 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002446 break;
2447 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002448
John McCallfaf5fb42010-08-26 23:41:50 +00002449 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002450 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002451 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002452 }
2453
David Blaikiebbafb8a2012-03-11 07:00:24 +00002454 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2455 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002456
David Blaikiebbafb8a2012-03-11 07:00:24 +00002457 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002458 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002459}
2460
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002461/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002462/// type chunk.
2463static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002464 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002465 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002466 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002467 if (!ND)
2468 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002469
2470 // Skip constructors and conversion functions, which have their return types
2471 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002472 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002473 return;
2474
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002475 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002476 QualType T;
2477 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002478 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002479 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002480 if (!BaseType.isNull())
2481 T = Method->getSendResultType(BaseType);
2482 else
2483 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002484 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002485 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002486 T = clang::TypeName::getFullyQualifiedType(T, Context);
2487 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002488 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002489 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002490 if (!BaseType.isNull())
2491 T = Ivar->getUsageType(BaseType);
2492 else
2493 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002494 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002495 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002496 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002497 if (!BaseType.isNull())
2498 T = Property->getUsageType(BaseType);
2499 else
2500 T = Property->getType();
2501 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002502
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002503 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2504 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002505
Fangrui Song050229d2018-11-24 00:14:31 +00002506 Result.AddResultTypeChunk(
2507 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002508}
2509
Richard Smith20e883e2015-04-29 23:20:19 +00002510static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002511 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002512 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002513 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2514 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002515 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002516 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002517 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002518 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002519 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002520 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002521 }
2522}
2523
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002524static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002525 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002526 std::string Result;
2527 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002528 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002529 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002530 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002531 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002532 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002533 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002534 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002535 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002536 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002537 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002538 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002539 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2540 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2541 switch (*nullability) {
2542 case NullabilityKind::NonNull:
2543 Result += "nonnull ";
2544 break;
2545
2546 case NullabilityKind::Nullable:
2547 Result += "nullable ";
2548 break;
2549
2550 case NullabilityKind::Unspecified:
2551 Result += "null_unspecified ";
2552 break;
2553 }
2554 }
2555 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002556 return Result;
2557}
2558
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002559/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002560/// block placeholder.
2561///
2562/// This function ignores things like typedefs and qualifiers in order to
2563/// present the most relevant and accurate block placeholders in code completion
2564/// results.
2565static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2566 FunctionTypeLoc &Block,
2567 FunctionProtoTypeLoc &BlockProto,
2568 bool SuppressBlock = false) {
2569 if (!TSInfo)
2570 return;
2571 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2572 while (true) {
2573 // Look through typedefs.
2574 if (!SuppressBlock) {
2575 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2576 if (TypeSourceInfo *InnerTSInfo =
2577 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2578 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2579 continue;
2580 }
2581 }
2582
2583 // Look through qualified types
2584 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2585 TL = QualifiedTL.getUnqualifiedLoc();
2586 continue;
2587 }
2588
2589 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2590 TL = AttrTL.getModifiedLoc();
2591 continue;
2592 }
2593 }
2594
2595 // Try to get the function prototype behind the block pointer type,
2596 // then we're done.
2597 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2598 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2599 Block = TL.getAs<FunctionTypeLoc>();
2600 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2601 }
2602 break;
2603 }
2604}
2605
Alex Lorenz920ae142016-10-18 10:38:58 +00002606static std::string
2607formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2608 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002609 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002610 bool SuppressBlock = false,
2611 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2612
Fangrui Song050229d2018-11-24 00:14:31 +00002613static std::string
2614FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2615 bool SuppressName = false, bool SuppressBlock = false,
2616 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Sam McCallbc7ff892019-04-04 11:34:18 +00002617 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.
2618 // It would be better to pass in the param Type, which is usually avaliable.
2619 // But this case is rare, so just pretend we fell back to int as elsewhere.
2620 if (!Param)
2621 return "int";
Douglas Gregore90dd002010-08-24 16:15:59 +00002622 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2623 if (Param->getType()->isDependentType() ||
2624 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002625 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002626 // containing that parameter's type.
2627 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002628
Douglas Gregor981a0c42010-08-29 19:47:46 +00002629 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002630 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002631
Douglas Gregor86b42682015-06-19 18:27:52 +00002632 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002633 if (ObjCSubsts)
2634 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2635 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002636 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002637 Result =
2638 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002639 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002640 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002641 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002642 } else {
2643 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002644 }
2645 return Result;
2646 }
Alex Lorenza1951202016-10-18 10:35:27 +00002647
Douglas Gregore90dd002010-08-24 16:15:59 +00002648 // The argument for a block pointer parameter is a block literal with
2649 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002650 FunctionTypeLoc Block;
2651 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002652 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2653 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002654 // Try to retrieve the block type information from the property if this is a
2655 // parameter in a setter.
2656 if (!Block && ObjCMethodParam &&
2657 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2658 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2659 ->findPropertyDecl(/*CheckOverrides=*/false))
2660 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2661 SuppressBlock);
2662 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002663
2664 if (!Block) {
2665 // We were unable to find a FunctionProtoTypeLoc with parameter names
2666 // for the block; just use the parameter type as a placeholder.
2667 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002668 if (!ObjCMethodParam && Param->getIdentifier())
2669 Result = Param->getIdentifier()->getName();
2670
Douglas Gregor86b42682015-06-19 18:27:52 +00002671 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002672
Douglas Gregore90dd002010-08-24 16:15:59 +00002673 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002674 Result = Type.getAsString(Policy);
2675 std::string Quals =
2676 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2677 if (!Quals.empty())
2678 Result = "(" + Quals + " " + Result + ")";
2679 if (Result.back() != ')')
2680 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002681 if (Param->getIdentifier())
2682 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002683 } else {
2684 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002685 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002686
Douglas Gregore90dd002010-08-24 16:15:59 +00002687 return Result;
2688 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002689
Douglas Gregore90dd002010-08-24 16:15:59 +00002690 // We have the function prototype behind the block pointer type, as it was
2691 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002692 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2693 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002694 ObjCSubsts);
2695}
2696
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002697/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002698/// declaration.
2699///
2700/// \param BlockDecl A declaration with an Objective-C block type.
2701///
2702/// \param Block The most relevant type location for that block type.
2703///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002704/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002705/// declaration is included in the resulting string.
2706static std::string
2707formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2708 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002709 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002710 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002711 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002712 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002713 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002714 ResultType =
2715 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2716 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002717 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002718 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002719
2720 // Format the parameter list.
2721 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002722 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002723 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002724 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002725 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002726 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002727 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002728 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002729 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002730 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002731 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002732 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002733 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002734 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002735
David Blaikie6adc78e2013-02-18 22:06:02 +00002736 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002737 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002738 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002739 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002740 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002741
Douglas Gregord793e7c2011-10-18 04:23:19 +00002742 if (SuppressBlock) {
2743 // Format as a parameter.
2744 Result = Result + " (^";
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 Result += ")";
2748 Result += Params;
2749 } else {
2750 // Format as a block literal argument.
2751 Result = '^' + Result;
2752 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002753
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002754 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002755 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002756 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002757
Douglas Gregore90dd002010-08-24 16:15:59 +00002758 return Result;
2759}
2760
Erik Verbruggen11338c52017-07-19 10:45:40 +00002761static std::string GetDefaultValueString(const ParmVarDecl *Param,
2762 const SourceManager &SM,
2763 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002764 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002765 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2766 bool Invalid = CharSrcRange.isInvalid();
2767 if (Invalid)
2768 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002769 StringRef srcText =
2770 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002771 if (Invalid)
2772 return "";
2773
2774 if (srcText.empty() || srcText == "=") {
2775 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002776 // This happens if the code is incorrect (for example class is forward
2777 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002778 return "";
2779 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002780 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002781 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2782 // this value always has (or always does not have) '=' in front of it
2783 if (DefValue.at(0) != '=') {
2784 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002785 // Lexer returns built-in types values without '=' and user-defined types
2786 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002787 return " = " + DefValue;
2788 }
2789 return " " + DefValue;
2790}
2791
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002792/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002793static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002794 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002795 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002796 CodeCompletionBuilder &Result,
2797 unsigned Start = 0,
2798 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002799 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002800
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002801 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002802 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002803
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002804 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002805 // When we see an optional default argument, put that argument and
2806 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002807 CodeCompletionBuilder Opt(Result.getAllocator(),
2808 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002809 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002810 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002811 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002812 Result.AddOptionalChunk(Opt.TakeString());
2813 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002814 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002815
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002816 if (FirstParameter)
2817 FirstParameter = false;
2818 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002819 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002820
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002821 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002822
Douglas Gregor3545ff42009-09-21 16:56:56 +00002823 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002824 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002825 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002826 PlaceholderStr +=
2827 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002828
Douglas Gregor400f5972010-08-31 05:13:43 +00002829 if (Function->isVariadic() && P == N - 1)
2830 PlaceholderStr += ", ...";
2831
Douglas Gregor3545ff42009-09-21 16:56:56 +00002832 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002833 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002834 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002835 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002836
Fangrui Song050229d2018-11-24 00:14:31 +00002837 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002838 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002839 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002840 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002841
Richard Smith20e883e2015-04-29 23:20:19 +00002842 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002843 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002844}
2845
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002846/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002847static void AddTemplateParameterChunks(
2848 ASTContext &Context, const PrintingPolicy &Policy,
2849 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2850 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002851 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002852
2853 // Prefer to take the template parameter names from the first declaration of
2854 // the template.
2855 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2856
Douglas Gregor3545ff42009-09-21 16:56:56 +00002857 TemplateParameterList *Params = Template->getTemplateParameters();
2858 TemplateParameterList::iterator PEnd = Params->end();
2859 if (MaxParameters)
2860 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002861 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2862 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002863 bool HasDefaultArg = false;
2864 std::string PlaceholderStr;
2865 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2866 if (TTP->wasDeclaredWithTypename())
2867 PlaceholderStr = "typename";
2868 else
2869 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002870
Douglas Gregor3545ff42009-09-21 16:56:56 +00002871 if (TTP->getIdentifier()) {
2872 PlaceholderStr += ' ';
2873 PlaceholderStr += TTP->getIdentifier()->getName();
2874 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002875
Douglas Gregor3545ff42009-09-21 16:56:56 +00002876 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002877 } else if (NonTypeTemplateParmDecl *NTTP =
2878 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002879 if (NTTP->getIdentifier())
2880 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002881 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002882 HasDefaultArg = NTTP->hasDefaultArgument();
2883 } else {
2884 assert(isa<TemplateTemplateParmDecl>(*P));
2885 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002886
Douglas Gregor3545ff42009-09-21 16:56:56 +00002887 // Since putting the template argument list into the placeholder would
2888 // be very, very long, we just use an abbreviation.
2889 PlaceholderStr = "template<...> class";
2890 if (TTP->getIdentifier()) {
2891 PlaceholderStr += ' ';
2892 PlaceholderStr += TTP->getIdentifier()->getName();
2893 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002894
Douglas Gregor3545ff42009-09-21 16:56:56 +00002895 HasDefaultArg = TTP->hasDefaultArgument();
2896 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002897
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002898 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002899 // When we see an optional default argument, put that argument and
2900 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002901 CodeCompletionBuilder Opt(Result.getAllocator(),
2902 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002903 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002904 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002905 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002906 P - Params->begin(), true);
2907 Result.AddOptionalChunk(Opt.TakeString());
2908 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002909 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002910
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002911 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002912
Douglas Gregor3545ff42009-09-21 16:56:56 +00002913 if (FirstParameter)
2914 FirstParameter = false;
2915 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002916 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002917
Douglas Gregor3545ff42009-09-21 16:56:56 +00002918 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002919 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002920 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002921 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002922}
2923
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002924/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002925/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002926static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2927 NestedNameSpecifier *Qualifier,
2928 bool QualifierIsInformative,
2929 ASTContext &Context,
2930 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002931 if (!Qualifier)
2932 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002933
Douglas Gregorf2510672009-09-21 19:57:38 +00002934 std::string PrintedNNS;
2935 {
2936 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002937 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002938 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002939 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002940 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002941 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002942 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002943}
2944
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002945static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002946AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002947 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002948 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002949 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00002950 return;
2951
Douglas Gregor304f9b02011-02-01 21:15:40 +00002952 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002953
Douglas Gregor304f9b02011-02-01 21:15:40 +00002954 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002955 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002956 Result.AddInformativeChunk(" const");
2957 return;
2958 }
2959
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002960 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002961 Result.AddInformativeChunk(" volatile");
2962 return;
2963 }
2964
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00002965 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002966 Result.AddInformativeChunk(" restrict");
2967 return;
2968 }
2969
2970 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002971 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002972 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002973 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002974 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002975 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002976 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002977 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002978 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002979}
2980
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002981/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002982static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002983 const NamedDecl *ND,
2984 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002985 DeclarationName Name = ND->getDeclName();
2986 if (!Name)
2987 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002988
Douglas Gregor0212fd72010-09-21 16:06:22 +00002989 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002990 case DeclarationName::CXXOperatorName: {
2991 const char *OperatorName = nullptr;
2992 switch (Name.getCXXOverloadedOperator()) {
2993 case OO_None:
2994 case OO_Conditional:
2995 case NUM_OVERLOADED_OPERATORS:
2996 OperatorName = "operator";
2997 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002998
Fangrui Song050229d2018-11-24 00:14:31 +00002999#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
3000 case OO_##Name: \
3001 OperatorName = "operator" Spelling; \
3002 break;
3003#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00003004#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003005
Fangrui Song050229d2018-11-24 00:14:31 +00003006 case OO_New:
3007 OperatorName = "operator new";
3008 break;
3009 case OO_Delete:
3010 OperatorName = "operator delete";
3011 break;
3012 case OO_Array_New:
3013 OperatorName = "operator new[]";
3014 break;
3015 case OO_Array_Delete:
3016 OperatorName = "operator delete[]";
3017 break;
3018 case OO_Call:
3019 OperatorName = "operator()";
3020 break;
3021 case OO_Subscript:
3022 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003023 break;
3024 }
Fangrui Song050229d2018-11-24 00:14:31 +00003025 Result.AddTypedTextChunk(OperatorName);
3026 break;
3027 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003028
Douglas Gregor0212fd72010-09-21 16:06:22 +00003029 case DeclarationName::Identifier:
3030 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003031 case DeclarationName::CXXDestructorName:
3032 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003033 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003034 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003035 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003036
Richard Smith35845152017-02-07 01:37:30 +00003037 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003038 case DeclarationName::CXXUsingDirective:
3039 case DeclarationName::ObjCZeroArgSelector:
3040 case DeclarationName::ObjCOneArgSelector:
3041 case DeclarationName::ObjCMultiArgSelector:
3042 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003043
Douglas Gregor0212fd72010-09-21 16:06:22 +00003044 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003045 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003046 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003047 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003048 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003049 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003050 Record = InjectedTy->getDecl();
3051 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003052 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003053 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003054 break;
3055 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003056
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003057 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003058 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003059 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003060 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003061 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003062 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003063 }
3064 break;
3065 }
3066 }
3067}
3068
Fangrui Song050229d2018-11-24 00:14:31 +00003069CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3070 Sema &S, const CodeCompletionContext &CCContext,
3071 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3072 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003073 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3074 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003075}
3076
Eric Liu00f43c92018-07-06 09:43:57 +00003077CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3078 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3079 CodeCompletionTUInfo &CCTUInfo) {
3080 assert(Kind == RK_Macro);
3081 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3082 const MacroInfo *MI = PP.getMacroInfo(Macro);
3083 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3084
3085 if (!MI || !MI->isFunctionLike())
3086 return Result.TakeString();
3087
3088 // Format a function-like macro with placeholders for the arguments.
3089 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3090 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3091
3092 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3093 if (MI->isC99Varargs()) {
3094 --AEnd;
3095
3096 if (A == AEnd) {
3097 Result.AddPlaceholderChunk("...");
3098 }
3099 }
3100
3101 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3102 if (A != MI->param_begin())
3103 Result.AddChunk(CodeCompletionString::CK_Comma);
3104
3105 if (MI->isVariadic() && (A + 1) == AEnd) {
3106 SmallString<32> Arg = (*A)->getName();
3107 if (MI->isC99Varargs())
3108 Arg += ", ...";
3109 else
3110 Arg += "...";
3111 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3112 break;
3113 }
3114
3115 // Non-variadic macros are simple.
3116 Result.AddPlaceholderChunk(
3117 Result.getAllocator().CopyString((*A)->getName()));
3118 }
3119 Result.AddChunk(CodeCompletionString::CK_RightParen);
3120 return Result.TakeString();
3121}
3122
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003123/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003124/// result.
3125///
3126/// \returns Either a new, heap-allocated code completion string describing
3127/// how to use this result, or NULL to indicate that the string or name of the
3128/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003129CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3130 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3131 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3132 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003133 if (Kind == RK_Macro)
3134 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3135
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003136 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003137
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003138 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003139 if (Kind == RK_Pattern) {
3140 Pattern->Priority = Priority;
3141 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003142
Douglas Gregor78254c82012-03-27 23:34:16 +00003143 if (Declaration) {
3144 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003145 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003146 if (const RawComment *RC =
3147 getPatternCompletionComment(Ctx, Declaration)) {
3148 Result.addBriefComment(RC->getBriefText(Ctx));
3149 Pattern->BriefComment = Result.getBriefComment();
3150 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003151 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003152
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003153 return Pattern;
3154 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003155
Douglas Gregorf09935f2009-12-01 05:55:20 +00003156 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003157 Result.AddTypedTextChunk(Keyword);
3158 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003159 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003160 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003161 return createCodeCompletionStringForDecl(
3162 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003163}
3164
3165CodeCompletionString *
3166CodeCompletionResult::createCodeCompletionStringForOverride(
3167 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3168 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3169 PrintingPolicy &Policy) {
3170 std::string OverrideSignature;
3171 llvm::raw_string_ostream OS(OverrideSignature);
3172 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3173 /*IncludeBriefComments=*/false,
3174 CCContext, Policy);
3175 printOverrideString(OS, CCS);
3176 OS << " override";
3177 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
3178 return Result.TakeString();
3179}
3180
3181CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3182 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3183 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3184 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003185 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003186 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003187
3188 if (IncludeBriefComments) {
3189 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003190 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003191 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003192 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003193 }
3194
Douglas Gregor9eb77012009-11-07 00:00:49 +00003195 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003196 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003197 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003198 Result.AddTextChunk("::");
3199 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003200 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003201
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003202 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3203 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003204
Douglas Gregorc3425b12015-07-07 06:20:19 +00003205 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003206
Fangrui Song050229d2018-11-24 00:14:31 +00003207 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003208 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003209 Ctx, Policy);
3210 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003211 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003212 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003213 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003214 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003215 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003216 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003217
Fangrui Song050229d2018-11-24 00:14:31 +00003218 if (const FunctionTemplateDecl *FunTmpl =
3219 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003220 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003221 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003222 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003223 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003224
Douglas Gregor3545ff42009-09-21 16:56:56 +00003225 // Figure out which template parameters are deduced (or have default
3226 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003227 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003228 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003229 unsigned LastDeducibleArgument;
3230 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3231 --LastDeducibleArgument) {
3232 if (!Deduced[LastDeducibleArgument - 1]) {
3233 // C++0x: Figure out if the template argument has a default. If so,
3234 // the user doesn't need to type this argument.
3235 // FIXME: We need to abstract template parameters better!
3236 bool HasDefaultArg = false;
3237 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003238 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003239 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3240 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003241 else if (NonTypeTemplateParmDecl *NTTP =
3242 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003243 HasDefaultArg = NTTP->hasDefaultArgument();
3244 else {
3245 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003246 HasDefaultArg =
3247 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003248 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003249
Douglas Gregor3545ff42009-09-21 16:56:56 +00003250 if (!HasDefaultArg)
3251 break;
3252 }
3253 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003254
Douglas Gregor3545ff42009-09-21 16:56:56 +00003255 if (LastDeducibleArgument) {
3256 // Some of the function template arguments cannot be deduced from a
3257 // function call, so we introduce an explicit template argument list
3258 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003259 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003260 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003261 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003262 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003263 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003264
Douglas Gregor3545ff42009-09-21 16:56:56 +00003265 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003266 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003267 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003268 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003269 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003270 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003271 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003272
Fangrui Song050229d2018-11-24 00:14:31 +00003273 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003274 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003275 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003276 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003277 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003278 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003279 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003280 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003281 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003282 }
Fangrui Song050229d2018-11-24 00:14:31 +00003283 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003284 Selector Sel = Method->getSelector();
3285 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003286 Result.AddTypedTextChunk(
3287 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003288 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003289 }
3290
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003291 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003292 SelName += ':';
3293 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003294 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003295 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003296 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003297
Douglas Gregor1b605f72009-11-19 01:08:35 +00003298 // If there is only one parameter, and we're past it, add an empty
3299 // typed-text chunk since there is nothing to type.
3300 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003301 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003302 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003303 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003304 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003305 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003306 P != PEnd; (void)++P, ++Idx) {
3307 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003308 std::string Keyword;
3309 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003310 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003311 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003312 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003313 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003314 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003315 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003316 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003317 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003318 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003319
Douglas Gregor1b605f72009-11-19 01:08:35 +00003320 // If we're before the starting parameter, skip the placeholder.
3321 if (Idx < StartParameter)
3322 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003323
3324 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003325 QualType ParamType = (*P)->getType();
3326 Optional<ArrayRef<QualType>> ObjCSubsts;
3327 if (!CCContext.getBaseType().isNull())
3328 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3329
3330 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3331 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003332 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003333 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003334 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003335 ParamType = ParamType.substObjCTypeArgs(
3336 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003337 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003338 ParamType);
3339 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003340 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003341 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003342 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003343 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003344
Douglas Gregor400f5972010-08-31 05:13:43 +00003345 if (Method->isVariadic() && (P + 1) == PEnd)
3346 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003347
Douglas Gregor95887f92010-07-08 23:20:03 +00003348 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003349 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003350 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003351 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003352 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003353 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003354 }
3355
Douglas Gregor04c5f972009-12-23 00:21:46 +00003356 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003357 if (Method->param_size() == 0) {
3358 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003359 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003360 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003361 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003362 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003363 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003364 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003365
Richard Smith20e883e2015-04-29 23:20:19 +00003366 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003367 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003368
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003369 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003370 }
3371
Douglas Gregorf09935f2009-12-01 05:55:20 +00003372 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003373 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003374 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003375
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003376 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003377 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003378 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003379}
3380
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003381const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3382 const NamedDecl *ND) {
3383 if (!ND)
3384 return nullptr;
3385 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3386 return RC;
3387
3388 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003389 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003390 if (!M)
3391 return nullptr;
3392 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3393 if (!PDecl)
3394 return nullptr;
3395
3396 return Ctx.getRawCommentForAnyRedecl(PDecl);
3397}
3398
3399const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3400 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003401 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003402 if (!M || !M->isPropertyAccessor())
3403 return nullptr;
3404
3405 // Provide code completion comment for self.GetterName where
3406 // GetterName is the getter method for a property with name
3407 // different from the property name (declared via a property
3408 // getter attribute.
3409 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3410 if (!PDecl)
3411 return nullptr;
3412 if (PDecl->getGetterName() == M->getSelector() &&
3413 PDecl->getIdentifier() != M->getIdentifier()) {
3414 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3415 return RC;
3416 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3417 return RC;
3418 }
3419 return nullptr;
3420}
3421
3422const RawComment *clang::getParameterComment(
3423 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003424 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003425 auto FDecl = Result.getFunction();
3426 if (!FDecl)
3427 return nullptr;
3428 if (ArgIndex < FDecl->getNumParams())
3429 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3430 return nullptr;
3431}
3432
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003433/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003434/// string.
3435static void AddOverloadParameterChunks(ASTContext &Context,
3436 const PrintingPolicy &Policy,
3437 const FunctionDecl *Function,
3438 const FunctionProtoType *Prototype,
3439 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003440 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003441 bool InOptional = false) {
3442 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003443 unsigned NumParams =
3444 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003445
3446 for (unsigned P = Start; P != NumParams; ++P) {
3447 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3448 // When we see an optional default argument, put that argument and
3449 // the remaining default arguments into a new, optional string.
3450 CodeCompletionBuilder Opt(Result.getAllocator(),
3451 Result.getCodeCompletionTUInfo());
3452 if (!FirstParameter)
3453 Opt.AddChunk(CodeCompletionString::CK_Comma);
3454 // Optional sections are nested.
3455 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3456 CurrentArg, P, /*InOptional=*/true);
3457 Result.AddOptionalChunk(Opt.TakeString());
3458 return;
3459 }
3460
3461 if (FirstParameter)
3462 FirstParameter = false;
3463 else
3464 Result.AddChunk(CodeCompletionString::CK_Comma);
3465
3466 InOptional = false;
3467
3468 // Format the placeholder string.
3469 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003470 if (Function) {
3471 const ParmVarDecl *Param = Function->getParamDecl(P);
3472 Placeholder = FormatFunctionParameter(Policy, Param);
3473 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003474 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3475 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003476 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003477 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003478 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003479
3480 if (P == CurrentArg)
3481 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003482 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003483 else
3484 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3485 }
3486
3487 if (Prototype && Prototype->isVariadic()) {
3488 CodeCompletionBuilder Opt(Result.getAllocator(),
3489 Result.getCodeCompletionTUInfo());
3490 if (!FirstParameter)
3491 Opt.AddChunk(CodeCompletionString::CK_Comma);
3492
3493 if (CurrentArg < NumParams)
3494 Opt.AddPlaceholderChunk("...");
3495 else
3496 Opt.AddCurrentParameterChunk("...");
3497
3498 Result.AddOptionalChunk(Opt.TakeString());
3499 }
3500}
3501
Douglas Gregorf0f51982009-09-23 00:34:09 +00003502CodeCompletionString *
3503CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003504 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3505 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003506 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003507
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003508 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003509 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3510 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003511 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003512 const FunctionProtoType *Proto =
3513 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003514 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003515 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003516 // highlighted ellipsis.
3517 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003518 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003519 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003520 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3521 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3522 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003523 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003524 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003525
3526 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003527 if (IncludeBriefComments) {
3528 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003529 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003530 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003531 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003532 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003533 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003534 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003535 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003536 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003537 }
Alp Toker314cc812014-01-25 16:55:45 +00003538
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003539 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003540 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3541 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003542 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003543
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003544 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003545}
3546
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003547unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003548 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003549 bool PreferredTypeIsPointer) {
3550 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003551
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003552 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003553 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003554 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003555 Priority = CCP_Constant;
3556 if (PreferredTypeIsPointer)
3557 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003558 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003559 // Treat "YES", "NO", "true", and "false" as constants.
3560 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3561 MacroName.equals("true") || MacroName.equals("false"))
3562 Priority = CCP_Constant;
3563 // Treat "bool" as a type.
3564 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003565 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003566
Douglas Gregor6e240332010-08-16 16:18:59 +00003567 return Priority;
3568}
3569
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003570CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003571 if (!D)
3572 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003573
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003574 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003575 case Decl::Enum:
3576 return CXCursor_EnumDecl;
3577 case Decl::EnumConstant:
3578 return CXCursor_EnumConstantDecl;
3579 case Decl::Field:
3580 return CXCursor_FieldDecl;
3581 case Decl::Function:
3582 return CXCursor_FunctionDecl;
3583 case Decl::ObjCCategory:
3584 return CXCursor_ObjCCategoryDecl;
3585 case Decl::ObjCCategoryImpl:
3586 return CXCursor_ObjCCategoryImplDecl;
3587 case Decl::ObjCImplementation:
3588 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003589
Fangrui Song050229d2018-11-24 00:14:31 +00003590 case Decl::ObjCInterface:
3591 return CXCursor_ObjCInterfaceDecl;
3592 case Decl::ObjCIvar:
3593 return CXCursor_ObjCIvarDecl;
3594 case Decl::ObjCMethod:
3595 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3596 ? CXCursor_ObjCInstanceMethodDecl
3597 : CXCursor_ObjCClassMethodDecl;
3598 case Decl::CXXMethod:
3599 return CXCursor_CXXMethod;
3600 case Decl::CXXConstructor:
3601 return CXCursor_Constructor;
3602 case Decl::CXXDestructor:
3603 return CXCursor_Destructor;
3604 case Decl::CXXConversion:
3605 return CXCursor_ConversionFunction;
3606 case Decl::ObjCProperty:
3607 return CXCursor_ObjCPropertyDecl;
3608 case Decl::ObjCProtocol:
3609 return CXCursor_ObjCProtocolDecl;
3610 case Decl::ParmVar:
3611 return CXCursor_ParmDecl;
3612 case Decl::Typedef:
3613 return CXCursor_TypedefDecl;
3614 case Decl::TypeAlias:
3615 return CXCursor_TypeAliasDecl;
3616 case Decl::TypeAliasTemplate:
3617 return CXCursor_TypeAliasTemplateDecl;
3618 case Decl::Var:
3619 return CXCursor_VarDecl;
3620 case Decl::Namespace:
3621 return CXCursor_Namespace;
3622 case Decl::NamespaceAlias:
3623 return CXCursor_NamespaceAlias;
3624 case Decl::TemplateTypeParm:
3625 return CXCursor_TemplateTypeParameter;
3626 case Decl::NonTypeTemplateParm:
3627 return CXCursor_NonTypeTemplateParameter;
3628 case Decl::TemplateTemplateParm:
3629 return CXCursor_TemplateTemplateParameter;
3630 case Decl::FunctionTemplate:
3631 return CXCursor_FunctionTemplate;
3632 case Decl::ClassTemplate:
3633 return CXCursor_ClassTemplate;
3634 case Decl::AccessSpec:
3635 return CXCursor_CXXAccessSpecifier;
3636 case Decl::ClassTemplatePartialSpecialization:
3637 return CXCursor_ClassTemplatePartialSpecialization;
3638 case Decl::UsingDirective:
3639 return CXCursor_UsingDirective;
3640 case Decl::StaticAssert:
3641 return CXCursor_StaticAssert;
3642 case Decl::Friend:
3643 return CXCursor_FriendDecl;
3644 case Decl::TranslationUnit:
3645 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003646
Fangrui Song050229d2018-11-24 00:14:31 +00003647 case Decl::Using:
3648 case Decl::UnresolvedUsingValue:
3649 case Decl::UnresolvedUsingTypename:
3650 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003651
Fangrui Song050229d2018-11-24 00:14:31 +00003652 case Decl::ObjCPropertyImpl:
3653 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3654 case ObjCPropertyImplDecl::Dynamic:
3655 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003656
Fangrui Song050229d2018-11-24 00:14:31 +00003657 case ObjCPropertyImplDecl::Synthesize:
3658 return CXCursor_ObjCSynthesizeDecl;
3659 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003660 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003661
3662 case Decl::Import:
3663 return CXCursor_ModuleImportDecl;
3664
3665 case Decl::ObjCTypeParam:
3666 return CXCursor_TemplateTypeParameter;
3667
3668 default:
3669 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3670 switch (TD->getTagKind()) {
3671 case TTK_Interface: // fall through
3672 case TTK_Struct:
3673 return CXCursor_StructDecl;
3674 case TTK_Class:
3675 return CXCursor_ClassDecl;
3676 case TTK_Union:
3677 return CXCursor_UnionDecl;
3678 case TTK_Enum:
3679 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003680 }
Fangrui Song050229d2018-11-24 00:14:31 +00003681 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003682 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003683
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003684 return CXCursor_UnexposedDecl;
3685}
3686
Douglas Gregor55b037b2010-07-08 20:55:51 +00003687static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003688 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003689 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003690 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003691
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003692 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003693
Eric Liu88de9f62018-09-19 09:34:55 +00003694 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3695 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003696 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003697 auto MD = PP.getMacroDefinition(M->first);
3698 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003699 MacroInfo *MI = MD.getMacroInfo();
3700 if (MI && MI->isUsedForHeaderGuard())
3701 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003702
Eric Liud485df12018-09-05 14:59:17 +00003703 Results.AddResult(
3704 Result(M->first, MI,
3705 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3706 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003707 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003708 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003709
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003710 Results.ExitScope();
3711}
3712
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003713static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003714 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003715 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003716
Douglas Gregorce0e8562010-08-23 21:54:33 +00003717 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003718
Douglas Gregorce0e8562010-08-23 21:54:33 +00003719 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3720 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003721 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003722 Results.AddResult(Result("__func__", CCP_Constant));
3723 Results.ExitScope();
3724}
3725
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003726static void HandleCodeCompleteResults(Sema *S,
3727 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003728 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003729 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003730 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003731 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003732 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003733}
3734
Ilya Biryukov41109672018-12-13 15:36:32 +00003735static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003736mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003737 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003738 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003739 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003740
John McCallfaf5fb42010-08-26 23:41:50 +00003741 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003742 return CodeCompletionContext::CCC_ClassStructUnion;
3743
John McCallfaf5fb42010-08-26 23:41:50 +00003744 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003745 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003746
John McCallfaf5fb42010-08-26 23:41:50 +00003747 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003748 return CodeCompletionContext::CCC_ObjCImplementation;
3749
John McCallfaf5fb42010-08-26 23:41:50 +00003750 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003751 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003752
John McCallfaf5fb42010-08-26 23:41:50 +00003753 case Sema::PCC_Template:
3754 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003755 if (S.CurContext->isFileContext())
3756 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003757 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003758 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003759 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003760
John McCallfaf5fb42010-08-26 23:41:50 +00003761 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003762 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003763
John McCallfaf5fb42010-08-26 23:41:50 +00003764 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003765 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003766 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003767 return CodeCompletionContext::CCC_ParenthesizedExpression;
3768 else
3769 return CodeCompletionContext::CCC_Expression;
3770
3771 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003772 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003773 case Sema::PCC_Condition:
3774 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3775 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003776
John McCallfaf5fb42010-08-26 23:41:50 +00003777 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003778 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003779
John McCallfaf5fb42010-08-26 23:41:50 +00003780 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003781 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003782
3783 case Sema::PCC_ParenthesizedExpression:
3784 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003785
Douglas Gregor80039242011-02-15 20:33:25 +00003786 case Sema::PCC_LocalDeclarationSpecifiers:
3787 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003788 }
David Blaikie8a40f702012-01-17 06:56:22 +00003789
3790 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003791}
3792
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003793/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003794/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003795/// overridden function as well as adding new functionality.
3796///
3797/// \param S The semantic analysis object for which we are generating results.
3798///
3799/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003800/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003801static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3802 ResultBuilder &Results) {
3803 // Look through blocks.
3804 DeclContext *CurContext = S.CurContext;
3805 while (isa<BlockDecl>(CurContext))
3806 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003807
Douglas Gregorac322ec2010-08-27 21:18:54 +00003808 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3809 if (!Method || !Method->isVirtual())
3810 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003811
3812 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003813 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003814 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003815 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003816 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003817
Douglas Gregor75acd922011-09-27 23:30:47 +00003818 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003819 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003820 CodeCompletionBuilder Builder(Results.getAllocator(),
3821 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003822 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3823 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003824
Douglas Gregorac322ec2010-08-27 21:18:54 +00003825 // If we need a nested-name-specifier, add one now.
3826 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003827 NestedNameSpecifier *NNS = getRequiredQualification(
3828 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003829 if (NNS) {
3830 std::string Str;
3831 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003832 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003833 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003834 }
3835 } else if (!InContext->Equals(Overridden->getDeclContext()))
3836 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003837
Fangrui Song050229d2018-11-24 00:14:31 +00003838 Builder.AddTypedTextChunk(
3839 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003840 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003841 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003842 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003843 if (FirstParam)
3844 FirstParam = false;
3845 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003846 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003847
Aaron Ballman43b68be2014-03-07 17:50:17 +00003848 Builder.AddPlaceholderChunk(
3849 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003850 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003851 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003852 Results.AddResult(CodeCompletionResult(
3853 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3854 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003855 Results.Ignore(Overridden);
3856 }
3857}
3858
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003859void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003860 ModuleIdPath Path) {
3861 typedef CodeCompletionResult Result;
3862 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003863 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003864 CodeCompletionContext::CCC_Other);
3865 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003866
Douglas Gregor07f43572012-01-29 18:15:03 +00003867 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003868 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003869 typedef CodeCompletionResult Result;
3870 if (Path.empty()) {
3871 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003872 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003873 PP.getHeaderSearchInfo().collectAllModules(Modules);
3874 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3875 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003876 Builder.getAllocator().CopyString(Modules[I]->Name));
3877 Results.AddResult(Result(
3878 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3879 Modules[I]->isAvailable() ? CXAvailability_Available
3880 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003881 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003882 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003883 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003884 Module *Mod =
3885 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3886 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003887 // Enumerate submodules.
3888 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003889 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003890 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003891 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003892
Douglas Gregor07f43572012-01-29 18:15:03 +00003893 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003894 Builder.getAllocator().CopyString((*Sub)->Name));
3895 Results.AddResult(Result(
3896 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3897 (*Sub)->isAvailable() ? CXAvailability_Available
3898 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003899 }
3900 }
3901 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003902 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003903 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003904 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003905}
3906
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003907void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003908 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003909 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003910 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003911 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003912 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003913
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003914 // Determine how to filter results, e.g., so that the names of
3915 // values (functions, enumerators, function templates, etc.) are
3916 // only allowed where we can have an expression.
3917 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003918 case PCC_Namespace:
3919 case PCC_Class:
3920 case PCC_ObjCInterface:
3921 case PCC_ObjCImplementation:
3922 case PCC_ObjCInstanceVariableList:
3923 case PCC_Template:
3924 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003925 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003926 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003927 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3928 break;
3929
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003930 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003931 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003932 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003933 case PCC_ForInit:
3934 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003935 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003936 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3937 else
3938 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003939
David Blaikiebbafb8a2012-03-11 07:00:24 +00003940 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003941 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003942 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003943
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003944 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003945 // Unfiltered
3946 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003947 }
3948
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003949 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003950 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00003951 auto ThisType = getCurrentThisType();
3952 if (!ThisType.isNull())
3953 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003954
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003955 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003956 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003957 CodeCompleter->includeGlobals(),
3958 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003959
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003960 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003961 Results.ExitScope();
3962
Douglas Gregorce0e8562010-08-23 21:54:33 +00003963 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003964 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003965 case PCC_Expression:
3966 case PCC_Statement:
3967 case PCC_RecoveryInFunction:
3968 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003969 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003970 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003971
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003972 case PCC_Namespace:
3973 case PCC_Class:
3974 case PCC_ObjCInterface:
3975 case PCC_ObjCImplementation:
3976 case PCC_ObjCInstanceVariableList:
3977 case PCC_Template:
3978 case PCC_MemberTemplate:
3979 case PCC_ForInit:
3980 case PCC_Condition:
3981 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003982 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003983 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003984 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003985
Douglas Gregor9eb77012009-11-07 00:00:49 +00003986 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003987 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003988
Douglas Gregor50832e02010-09-20 22:39:41 +00003989 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003990 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003991}
3992
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003993static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003994 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003995 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00003996 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003997 ResultBuilder &Results);
3998
3999void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
4000 bool AllowNonIdentifiers,
4001 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00004002 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004003 ResultBuilder Results(
4004 *this, CodeCompleter->getAllocator(),
4005 CodeCompleter->getCodeCompletionTUInfo(),
4006 AllowNestedNameSpecifiers
4007 // FIXME: Try to separate codepath leading here to deduce whether we
4008 // need an existing symbol or a new one.
4009 ? CodeCompletionContext::CCC_SymbolOrNewName
4010 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004011 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004012
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004013 // Type qualifiers can come after names.
4014 Results.AddResult(Result("const"));
4015 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004016 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004017 Results.AddResult(Result("restrict"));
4018
David Blaikiebbafb8a2012-03-11 07:00:24 +00004019 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004020 if (getLangOpts().CPlusPlus11 &&
4021 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4022 DS.getTypeSpecType() == DeclSpec::TST_struct))
4023 Results.AddResult("final");
4024
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004025 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004026 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004027 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004028
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004029 // Add nested-name-specifiers.
4030 if (AllowNestedNameSpecifiers) {
4031 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004032 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004033 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4034 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004035 CodeCompleter->includeGlobals(),
4036 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004037 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004038 }
4039 }
4040 Results.ExitScope();
4041
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004042 // If we're in a context where we might have an expression (rather than a
4043 // declaration), and what we've seen so far is an Objective-C type that could
4044 // be a receiver of a class message, this may be a class message send with
4045 // the initial opening bracket '[' missing. Add appropriate completions.
4046 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004047 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004048 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004049 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4050 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004051 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004052 (S->getFlags() & Scope::DeclScope) != 0 &&
4053 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004054 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4055 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004056 ParsedType T = DS.getRepAsType();
4057 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004058 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004059 }
4060
Douglas Gregor56ccce02010-08-24 04:59:56 +00004061 // Note that we intentionally suppress macro results here, since we do not
4062 // encourage using macros to produce the names of entities.
4063
Fangrui Song050229d2018-11-24 00:14:31 +00004064 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004065 Results.data(), Results.size());
4066}
4067
Douglas Gregor68762e72010-08-23 21:17:50 +00004068struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004069 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4070 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004071 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004072 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004073
Douglas Gregor68762e72010-08-23 21:17:50 +00004074 QualType PreferredType;
4075 bool IntegralConstantExpression;
4076 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004077 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004078 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004079};
4080
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004081namespace {
4082/// Information that allows to avoid completing redundant enumerators.
4083struct CoveredEnumerators {
4084 llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
4085 NestedNameSpecifier *SuggestedQualifier = nullptr;
4086};
4087} // namespace
4088
4089static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
4090 EnumDecl *Enum, DeclContext *CurContext,
4091 const CoveredEnumerators &Enumerators) {
4092 NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
4093 if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
4094 // If there are no prior enumerators in C++, check whether we have to
4095 // qualify the names of the enumerators that we suggest, because they
4096 // may not be visible in this scope.
4097 Qualifier = getRequiredQualification(Context, CurContext, Enum);
4098 }
4099
4100 Results.EnterNewScope();
4101 for (auto *E : Enum->enumerators()) {
4102 if (Enumerators.Seen.count(E))
4103 continue;
4104
4105 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
4106 Results.AddResult(R, CurContext, nullptr, false);
4107 }
4108 Results.ExitScope();
4109}
4110
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004111/// Try to find a corresponding FunctionProtoType for function-like types (e.g.
4112/// function pointers, std::function, etc).
4113static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) {
4114 assert(!T.isNull());
4115 // Try to extract first template argument from std::function<> and similar.
4116 // Note we only handle the sugared types, they closely match what users wrote.
4117 // We explicitly choose to not handle ClassTemplateSpecializationDecl.
4118 if (auto *Specialization = T->getAs<TemplateSpecializationType>()) {
4119 if (Specialization->getNumArgs() != 1)
4120 return nullptr;
4121 const TemplateArgument &Argument = Specialization->getArg(0);
4122 if (Argument.getKind() != TemplateArgument::Type)
4123 return nullptr;
4124 return Argument.getAsType()->getAs<FunctionProtoType>();
4125 }
4126 // Handle other cases.
4127 if (T->isPointerType())
4128 T = T->getPointeeType();
4129 return T->getAs<FunctionProtoType>();
4130}
4131
4132/// Adds a pattern completion for a lambda expression with the specified
4133/// parameter types and placeholders for parameter names.
4134static void AddLambdaCompletion(ResultBuilder &Results,
4135 llvm::ArrayRef<QualType> Parameters,
4136 const LangOptions &LangOpts) {
Ilya Biryukovfd11a5f2019-05-23 16:39:26 +00004137 if (!Results.includeCodePatterns())
4138 return;
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004139 CodeCompletionBuilder Completion(Results.getAllocator(),
4140 Results.getCodeCompletionTUInfo());
4141 // [](<parameters>) {}
4142 Completion.AddChunk(CodeCompletionString::CK_LeftBracket);
4143 Completion.AddPlaceholderChunk("=");
4144 Completion.AddChunk(CodeCompletionString::CK_RightBracket);
4145 if (!Parameters.empty()) {
4146 Completion.AddChunk(CodeCompletionString::CK_LeftParen);
4147 bool First = true;
4148 for (auto Parameter : Parameters) {
4149 if (!First)
4150 Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma);
4151 else
4152 First = false;
4153
4154 constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!";
4155 std::string Type = NamePlaceholder;
4156 Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts));
4157 llvm::StringRef Prefix, Suffix;
4158 std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder);
4159 Prefix = Prefix.rtrim();
4160 Suffix = Suffix.ltrim();
4161
4162 Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix));
4163 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4164 Completion.AddPlaceholderChunk("parameter");
4165 Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix));
4166 };
4167 Completion.AddChunk(CodeCompletionString::CK_RightParen);
4168 }
4169 Completion.AddChunk(CodeCompletionString::CK_LeftBrace);
4170 Completion.AddPlaceholderChunk("body");
4171 Completion.AddChunk(CodeCompletionString::CK_RightBrace);
4172
4173 Results.AddResult(Completion.TakeString());
4174}
4175
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004176/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004177/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004178void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004179 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004180 ResultBuilder Results(
4181 *this, CodeCompleter->getAllocator(),
4182 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004183 CodeCompletionContext(
4184 Data.IsParenthesized
4185 ? CodeCompletionContext::CCC_ParenthesizedExpression
4186 : CodeCompletionContext::CCC_Expression,
4187 Data.PreferredType));
4188 auto PCC =
4189 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004190 if (Data.ObjCCollection)
4191 Results.setFilter(&ResultBuilder::IsObjCCollection);
4192 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004193 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004194 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004195 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4196 else
4197 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004198
4199 if (!Data.PreferredType.isNull())
4200 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004201
Douglas Gregor68762e72010-08-23 21:17:50 +00004202 // Ignore any declarations that we were told that we don't care about.
4203 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4204 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004205
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004206 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004207 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004208 CodeCompleter->includeGlobals(),
4209 CodeCompleter->loadExternal());
4210
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004211 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004212 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004213 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004214
Douglas Gregor55b037b2010-07-08 20:55:51 +00004215 bool PreferredTypeIsPointer = false;
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004216 if (!Data.PreferredType.isNull()) {
Fangrui Song050229d2018-11-24 00:14:31 +00004217 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4218 Data.PreferredType->isMemberPointerType() ||
4219 Data.PreferredType->isBlockPointerType();
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004220 if (Data.PreferredType->isEnumeralType()) {
4221 EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();
4222 if (auto *Def = Enum->getDefinition())
4223 Enum = Def;
4224 // FIXME: collect covered enumerators in cases like:
4225 // if (x == my_enum::one) { ... } else if (x == ^) {}
4226 AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators());
4227 }
4228 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004229
Fangrui Song050229d2018-11-24 00:14:31 +00004230 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004231 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004232 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004233
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004234 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004235 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4236 PreferredTypeIsPointer);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004237
4238 // Complete a lambda expression when preferred type is a function.
4239 if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) {
4240 if (const FunctionProtoType *F =
4241 TryDeconstructFunctionLike(Data.PreferredType))
4242 AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts());
4243 }
4244
Eric Liuf5ba09f2018-07-04 10:01:18 +00004245 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4246 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004247}
4248
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004249void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4250 bool IsParenthesized) {
4251 return CodeCompleteExpression(
4252 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004253}
4254
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004255void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4256 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004257 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004258 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004259 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004260 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004261}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004262
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004263/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004264/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004265typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004266
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004267/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004268static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4269 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4270 if (Interface->hasDefinition())
4271 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004272
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004273 return Interface;
4274 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004275
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004276 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4277 if (Protocol->hasDefinition())
4278 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004279
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004280 return Protocol;
4281 }
4282 return Container;
4283}
4284
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004285/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004286/// declaration \p BD.
4287static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4288 CodeCompletionBuilder &Builder,
4289 const NamedDecl *BD,
4290 const FunctionTypeLoc &BlockLoc,
4291 const FunctionProtoTypeLoc &BlockProtoLoc) {
4292 Builder.AddResultTypeChunk(
4293 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4294 Policy, Builder.getAllocator()));
4295
4296 AddTypedNameChunk(Context, Policy, BD, Builder);
4297 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4298
4299 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4300 Builder.AddPlaceholderChunk("...");
4301 } else {
4302 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4303 if (I)
4304 Builder.AddChunk(CodeCompletionString::CK_Comma);
4305
4306 // Format the placeholder string.
4307 std::string PlaceholderStr =
4308 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4309
4310 if (I == N - 1 && BlockProtoLoc &&
4311 BlockProtoLoc.getTypePtr()->isVariadic())
4312 PlaceholderStr += ", ...";
4313
4314 // Add the placeholder string.
4315 Builder.AddPlaceholderChunk(
4316 Builder.getAllocator().CopyString(PlaceholderStr));
4317 }
4318 }
4319
4320 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4321}
4322
Fangrui Song050229d2018-11-24 00:14:31 +00004323static void
4324AddObjCProperties(const CodeCompletionContext &CCContext,
4325 ObjCContainerDecl *Container, bool AllowCategories,
4326 bool AllowNullaryMethods, DeclContext *CurContext,
4327 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4328 bool IsBaseExprStatement = false,
4329 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004330 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004331
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004332 // Retrieve the definition.
4333 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004334
Douglas Gregor9291bad2009-11-18 01:29:26 +00004335 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004336 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004337 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004338 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004339
Alex Lorenzbaef8022016-11-09 13:43:18 +00004340 // FIXME: Provide block invocation completion for non-statement
4341 // expressions.
4342 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4343 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004344 Result R = Result(P, Results.getBasePriority(P), nullptr);
4345 if (!InOriginalClass)
4346 setInBaseClass(R);
4347 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004348 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004349 }
4350
4351 // Block setter and invocation completion is provided only when we are able
4352 // to find the FunctionProtoTypeLoc with parameter names for the block.
4353 FunctionTypeLoc BlockLoc;
4354 FunctionProtoTypeLoc BlockProtoLoc;
4355 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4356 BlockProtoLoc);
4357 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004358 Result R = Result(P, Results.getBasePriority(P), nullptr);
4359 if (!InOriginalClass)
4360 setInBaseClass(R);
4361 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004362 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004363 }
4364
4365 // The default completion result for block properties should be the block
4366 // invocation completion when the base expression is a statement.
4367 CodeCompletionBuilder Builder(Results.getAllocator(),
4368 Results.getCodeCompletionTUInfo());
4369 AddObjCBlockCall(Container->getASTContext(),
4370 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4371 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004372 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4373 if (!InOriginalClass)
4374 setInBaseClass(R);
4375 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004376
4377 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004378 // statement and the block property is mutable.
4379 if (!P->isReadOnly()) {
4380 CodeCompletionBuilder Builder(Results.getAllocator(),
4381 Results.getCodeCompletionTUInfo());
4382 AddResultTypeChunk(Container->getASTContext(),
4383 getCompletionPrintingPolicy(Results.getSema()), P,
4384 CCContext.getBaseType(), Builder);
4385 Builder.AddTypedTextChunk(
4386 Results.getAllocator().CopyString(P->getName()));
4387 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004388
Alex Lorenzbaef8022016-11-09 13:43:18 +00004389 std::string PlaceholderStr = formatBlockPlaceholder(
4390 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4391 BlockProtoLoc, /*SuppressBlockName=*/true);
4392 // Add the placeholder string.
4393 Builder.AddPlaceholderChunk(
4394 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004395
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004396 // When completing blocks properties that return void the default
4397 // property completion result should show up before the setter,
4398 // otherwise the setter completion should show up before the default
4399 // property completion, as we normally want to use the result of the
4400 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004401 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004402 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004403 Results.getBasePriority(P) +
4404 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4405 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004406 : -CCD_BlockPropertySetter));
4407 if (!InOriginalClass)
4408 setInBaseClass(R);
4409 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004410 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004411 };
4412
4413 if (IsClassProperty) {
4414 for (const auto *P : Container->class_properties())
4415 AddProperty(P);
4416 } else {
4417 for (const auto *P : Container->instance_properties())
4418 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004419 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004420
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004421 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004422 if (AllowNullaryMethods) {
4423 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004424 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004425 // Adds a method result
4426 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4427 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4428 if (!Name)
4429 return;
4430 if (!AddedProperties.insert(Name).second)
4431 return;
4432 CodeCompletionBuilder Builder(Results.getAllocator(),
4433 Results.getCodeCompletionTUInfo());
4434 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4435 Builder.AddTypedTextChunk(
4436 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004437 Result R = Result(Builder.TakeString(), M,
4438 CCP_MemberDeclaration + CCD_MethodAsProperty);
4439 if (!InOriginalClass)
4440 setInBaseClass(R);
4441 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004442 };
4443
4444 if (IsClassProperty) {
4445 for (const auto *M : Container->methods()) {
4446 // Gather the class method that can be used as implicit property
4447 // getters. Methods with arguments or methods that return void aren't
4448 // added to the results as they can't be used as a getter.
4449 if (!M->getSelector().isUnarySelector() ||
4450 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4451 continue;
4452 AddMethod(M);
4453 }
4454 } else {
4455 for (auto *M : Container->methods()) {
4456 if (M->getSelector().isUnarySelector())
4457 AddMethod(M);
4458 }
Douglas Gregor95147142011-05-05 15:50:42 +00004459 }
4460 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004461
Douglas Gregor9291bad2009-11-18 01:29:26 +00004462 // Add properties in referenced protocols.
4463 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004464 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004465 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004466 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004467 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004468 /*InOriginalClass*/ false);
4469 } else if (ObjCInterfaceDecl *IFace =
4470 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004471 if (AllowCategories) {
4472 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004473 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004474 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004475 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004476 IsBaseExprStatement, IsClassProperty,
4477 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004478 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004479
Douglas Gregor9291bad2009-11-18 01:29:26 +00004480 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004481 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004482 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004483 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004484 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004485 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004486
Douglas Gregor9291bad2009-11-18 01:29:26 +00004487 // Look in the superclass.
4488 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004489 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004490 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004491 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004492 /*InOriginalClass*/ false);
4493 } else if (const auto *Category =
4494 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004495 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004496 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004497 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004498 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004499 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004500 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004501 }
4502}
4503
Fangrui Song050229d2018-11-24 00:14:31 +00004504static void
4505AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
4506 Scope *S, QualType BaseType, RecordDecl *RD,
4507 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004508 // Indicate that we are performing a member access, and the cv-qualifiers
4509 // for the base object type.
4510 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4511
4512 // Access to a C/C++ class, struct, or union.
4513 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004514 std::vector<FixItHint> FixIts;
4515 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004516 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004517 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004518 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004519 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004520 /*IncludeDependentBases=*/true,
4521 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004522
4523 if (SemaRef.getLangOpts().CPlusPlus) {
4524 if (!Results.empty()) {
4525 // The "template" keyword can follow "->" or "." in the grammar.
4526 // However, we only want to suggest the template keyword if something
4527 // is dependent.
4528 bool IsDependent = BaseType->isDependentType();
4529 if (!IsDependent) {
4530 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4531 if (DeclContext *Ctx = DepScope->getEntity()) {
4532 IsDependent = Ctx->isDependentContext();
4533 break;
4534 }
4535 }
4536
4537 if (IsDependent)
4538 Results.AddResult(CodeCompletionResult("template"));
4539 }
4540 }
4541}
4542
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004543void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004544 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004545 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004546 bool IsBaseExprStatement,
4547 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004548 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004549 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004550
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004551 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4552 if (ConvertedBase.isInvalid())
4553 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004554 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4555
4556 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004557
4558 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004559 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004560 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004561 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004562
Douglas Gregor21325842011-07-07 16:03:39 +00004563 if (IsArrow) {
4564 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004565 } else {
4566 if (ConvertedBaseType->isObjCObjectPointerType() ||
4567 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004568 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004569 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004570 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4571 }
4572 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004573
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004574 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004575 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004576 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004577 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004578 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004579
Fangrui Song050229d2018-11-24 00:14:31 +00004580 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4581 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004582 if (!Base)
4583 return false;
4584
4585 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4586 if (ConvertedBase.isInvalid())
4587 return false;
4588 Base = ConvertedBase.get();
4589
4590 QualType BaseType = Base->getType();
4591
4592 if (IsArrow) {
4593 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4594 BaseType = Ptr->getPointeeType();
4595 else if (BaseType->isObjCObjectPointerType())
4596 /*Do nothing*/;
4597 else
4598 return false;
4599 }
4600
4601 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4602 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4603 Record->getDecl(),
4604 std::move(AccessOpFixIt));
4605 } else if (const auto *TST =
4606 BaseType->getAs<TemplateSpecializationType>()) {
4607 TemplateName TN = TST->getTemplateName();
4608 if (const auto *TD =
4609 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4610 CXXRecordDecl *RD = TD->getTemplatedDecl();
4611 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4612 std::move(AccessOpFixIt));
4613 }
4614 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4615 if (auto *RD = ICNT->getDecl())
4616 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4617 std::move(AccessOpFixIt));
4618 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4619 // Objective-C property reference.
4620 AddedPropertiesSet AddedProperties;
4621
4622 if (const ObjCObjectPointerType *ObjCPtr =
4623 BaseType->getAsObjCInterfacePointerType()) {
4624 // Add property results based on our interface.
4625 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4626 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4627 /*AllowNullaryMethods=*/true, CurContext,
4628 AddedProperties, Results, IsBaseExprStatement);
4629 }
4630
4631 // Add properties from the protocols in a qualified interface.
4632 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4633 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4634 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004635 IsBaseExprStatement, /*IsClassProperty*/ false,
4636 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004637 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4638 (!IsArrow && BaseType->isObjCObjectType())) {
4639 // Objective-C instance variable access.
4640 ObjCInterfaceDecl *Class = nullptr;
4641 if (const ObjCObjectPointerType *ObjCPtr =
4642 BaseType->getAs<ObjCObjectPointerType>())
4643 Class = ObjCPtr->getInterfaceDecl();
4644 else
4645 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4646
4647 // Add all ivars from this class and its superclasses.
4648 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004649 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004650 Results.setFilter(&ResultBuilder::IsObjCIvar);
4651 LookupVisibleDecls(
4652 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4653 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4654 }
4655 }
4656
4657 // FIXME: How do we cope with isa?
4658 return true;
4659 };
4660
Douglas Gregor9291bad2009-11-18 01:29:26 +00004661 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004662
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004663 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4664 if (CodeCompleter->includeFixIts()) {
4665 const CharSourceRange OpRange =
4666 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4667 CompletionSucceded |= DoCompletion(
4668 OtherOpBase, !IsArrow,
4669 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004670 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004671
Douglas Gregor9291bad2009-11-18 01:29:26 +00004672 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004673
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004674 if (!CompletionSucceded)
4675 return;
4676
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004677 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004678 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4679 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004680}
4681
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004682void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4683 IdentifierInfo &ClassName,
4684 SourceLocation ClassNameLoc,
4685 bool IsBaseExprStatement) {
4686 IdentifierInfo *ClassNamePtr = &ClassName;
4687 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4688 if (!IFace)
4689 return;
4690 CodeCompletionContext CCContext(
4691 CodeCompletionContext::CCC_ObjCPropertyAccess);
4692 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4693 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4694 &ResultBuilder::IsMember);
4695 Results.EnterNewScope();
4696 AddedPropertiesSet AddedProperties;
4697 AddObjCProperties(CCContext, IFace, true,
4698 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4699 Results, IsBaseExprStatement,
4700 /*IsClassProperty=*/true);
4701 Results.ExitScope();
4702 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4703 Results.data(), Results.size());
4704}
4705
Faisal Vali090da2d2018-01-01 18:23:28 +00004706void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004707 if (!CodeCompleter)
4708 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004709
4710 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004711 enum CodeCompletionContext::Kind ContextKind =
4712 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004713 switch ((DeclSpec::TST)TagSpec) {
4714 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004715 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004716 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004717 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004718
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004719 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004720 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004721 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004722 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004723
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004724 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004725 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004726 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004727 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004728 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004729 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004730
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004731 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004732 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004733 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004734
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004735 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4736 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004737 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004738
4739 // First pass: look for tags.
4740 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004741 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004742 CodeCompleter->includeGlobals(),
4743 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004744
Douglas Gregor39982192010-08-15 06:18:01 +00004745 if (CodeCompleter->includeGlobals()) {
4746 // Second pass: look for nested name specifiers.
4747 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004748 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4749 CodeCompleter->includeGlobals(),
4750 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004751 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004752
Douglas Gregor0ac41382010-09-23 23:01:17 +00004753 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004754 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004755}
4756
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004757static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4758 const LangOptions &LangOpts) {
4759 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4760 Results.AddResult("const");
4761 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4762 Results.AddResult("volatile");
4763 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4764 Results.AddResult("restrict");
4765 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4766 Results.AddResult("_Atomic");
4767 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4768 Results.AddResult("__unaligned");
4769}
4770
Douglas Gregor28c78432010-08-27 17:35:51 +00004771void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004772 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004773 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004774 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004775 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004776 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004777 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004778 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004779 Results.data(), Results.size());
4780}
4781
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004782void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4783 const VirtSpecifiers *VS) {
4784 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4785 CodeCompleter->getCodeCompletionTUInfo(),
4786 CodeCompletionContext::CCC_TypeQualifiers);
4787 Results.EnterNewScope();
4788 AddTypeQualifierResults(DS, Results, LangOpts);
4789 if (LangOpts.CPlusPlus11) {
4790 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004791 if (D.getContext() == DeclaratorContext::MemberContext &&
4792 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004793 if (!VS || !VS->isFinalSpecified())
4794 Results.AddResult("final");
4795 if (!VS || !VS->isOverrideSpecified())
4796 Results.AddResult("override");
4797 }
4798 }
4799 Results.ExitScope();
4800 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4801 Results.data(), Results.size());
4802}
4803
Benjamin Kramer72dae622016-02-18 15:30:24 +00004804void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4805 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4806}
4807
Douglas Gregord328d572009-09-21 18:10:23 +00004808void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004809 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004810 return;
John McCall5939b162011-08-06 07:30:58 +00004811
Richard Smithef6c43d2018-07-26 18:41:30 +00004812 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004813 // Condition expression might be invalid, do not continue in this case.
4814 if (!Switch->getCond())
4815 return;
John McCall5939b162011-08-06 07:30:58 +00004816 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4817 if (!type->isEnumeralType()) {
4818 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004819 Data.IntegralConstantExpression = true;
4820 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004821 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004822 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004823
Douglas Gregord328d572009-09-21 18:10:23 +00004824 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004825 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004826 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004827 if (EnumDecl *Def = Enum->getDefinition())
4828 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004829
Douglas Gregord328d572009-09-21 18:10:23 +00004830 // Determine which enumerators we have already seen in the switch statement.
4831 // FIXME: Ideally, we would also be able to look *past* the code-completion
4832 // token, in case we are code-completing in the middle of the switch and not
4833 // at the end. However, we aren't able to do so at the moment.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004834 CoveredEnumerators Enumerators;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004835 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004836 SC = SC->getNextSwitchCase()) {
4837 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4838 if (!Case)
4839 continue;
4840
4841 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004842 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4843 if (auto *Enumerator =
4844 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004845 // We look into the AST of the case statement to determine which
4846 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004847 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004848 // values of each enumerator. However, value-based approach would not
4849 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004850 // template are type- and value-dependent.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004851 Enumerators.Seen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004852
Douglas Gregorf2510672009-09-21 19:57:38 +00004853 // If this is a qualified-id, keep track of the nested-name-specifier
4854 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004855 //
4856 // switch (TagD.getKind()) {
4857 // case TagDecl::TK_enum:
4858 // break;
4859 // case XXX
4860 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004861 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004862 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4863 // TK_struct, and TK_class.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004864 Enumerators.SuggestedQualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004865 }
4866 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004867
Douglas Gregord328d572009-09-21 18:10:23 +00004868 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004869 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004870 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004871 CodeCompletionContext::CCC_Expression);
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004872 AddEnumerators(Results, Context, Enum, CurContext, Enumerators);
Douglas Gregor285560922010-04-06 20:02:15 +00004873
Douglas Gregor21325842011-07-07 16:03:39 +00004874 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004875 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004876 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004877 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4878 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004879}
4880
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004881static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004882 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004883 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004884
4885 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004886 if (!Args[I])
4887 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004888
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004889 return false;
4890}
4891
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004892typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4893
Fangrui Song050229d2018-11-24 00:14:31 +00004894static void mergeCandidatesWithResults(
4895 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
4896 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Fangrui Song899d1392019-04-24 14:43:05 +00004897 // Sort the overload candidate set by placing the best overloads first.
4898 llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
4899 const OverloadCandidate &Y) {
4900 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4901 CandidateSet.getKind());
4902 });
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004903
Fangrui Song899d1392019-04-24 14:43:05 +00004904 // Add the remaining viable overload candidates as code-completion results.
4905 for (OverloadCandidate &Candidate : CandidateSet) {
4906 if (Candidate.Function && Candidate.Function->isDeleted())
4907 continue;
4908 if (Candidate.Viable)
4909 Results.push_back(ResultCandidate(Candidate.Function));
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004910 }
4911}
4912
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004913/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004914/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004915static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00004916 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004917
4918 // Given the overloads 'Candidates' for a function call matching all arguments
4919 // up to N, return the type of the Nth parameter if it is the same for all
4920 // overload candidates.
4921 QualType ParamType;
4922 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00004923 if (const auto *FType = Candidate.getFunctionType())
4924 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004925 if (N < Proto->getNumParams()) {
4926 if (ParamType.isNull())
4927 ParamType = Proto->getParamType(N);
4928 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00004929 ParamType.getNonReferenceType(),
4930 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004931 // Otherwise return a default-constructed QualType.
4932 return QualType();
4933 }
4934 }
4935
4936 return ParamType;
4937}
4938
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004939static QualType
4940ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4941 MutableArrayRef<ResultCandidate> Candidates,
4942 unsigned CurrentArg, SourceLocation OpenParLoc) {
4943 if (Candidates.empty())
4944 return QualType();
4945 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4946 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4947 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004948}
4949
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004950QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4951 ArrayRef<Expr *> Args,
4952 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004953 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004954 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004955
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004956 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004957 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004958 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4959 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004960 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004961 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004962
John McCall57500772009-12-16 12:17:52 +00004963 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004964 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004965 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004966
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004967 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004968
John McCall57500772009-12-16 12:17:52 +00004969 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004970 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004971 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004972 /*PartialOverloading=*/true);
4973 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4974 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4975 if (UME->hasExplicitTemplateArgs()) {
4976 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4977 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004978 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004979
4980 // Add the base as first argument (use a nullptr if the base is implicit).
4981 SmallVector<Expr *, 12> ArgExprs(
4982 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004983 ArgExprs.append(Args.begin(), Args.end());
4984 UnresolvedSet<8> Decls;
4985 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004986 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004987 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4988 /*SuppressUsedConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00004989 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004990 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004991 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004992 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004993 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00004994 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004995 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004996 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004997 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004998 !FD->getType()->getAs<FunctionProtoType>())
4999 Results.push_back(ResultCandidate(FD));
5000 else
5001 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
5002 Args, CandidateSet,
5003 /*SuppressUsedConversions=*/false,
5004 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005005
5006 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
5007 // If expression's type is CXXRecordDecl, it may overload the function
5008 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005009 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00005010 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00005011 DeclarationName OpName =
5012 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005013 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
5014 LookupQualifiedName(R, DC);
5015 R.suppressDiagnostics();
5016 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
5017 ArgExprs.append(Args.begin(), Args.end());
5018 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
5019 /*ExplicitArgs=*/nullptr,
5020 /*SuppressUsedConversions=*/false,
5021 /*PartialOverloading=*/true);
5022 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005023 } else {
5024 // Lastly we check whether expression's type is function pointer or
5025 // function.
5026 QualType T = NakedFn->getType();
5027 if (!T->getPointeeType().isNull())
5028 T = T->getPointeeType();
5029
5030 if (auto FP = T->getAs<FunctionProtoType>()) {
5031 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00005032 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005033 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005034 Results.push_back(ResultCandidate(FP));
5035 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005036 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005037 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005038 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005039 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005040 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005041 QualType ParamType =
5042 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
5043 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005044}
5045
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005046QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
5047 SourceLocation Loc,
5048 ArrayRef<Expr *> Args,
5049 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005050 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005051 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005052
5053 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00005054 CXXRecordDecl *RD =
5055 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005056 if (!RD)
5057 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00005058
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005059 // FIXME: Provide support for member initializers.
5060 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005061
5062 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
5063
Fangrui Song050229d2018-11-24 00:14:31 +00005064 for (NamedDecl *C : LookupConstructors(RD)) {
5065 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
5066 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
5067 CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005068 /*SuppressUsedConversions=*/false,
Richard Smith76b90272019-05-09 03:59:21 +00005069 /*PartialOverloading=*/true,
5070 /*AllowExplicit*/ true);
Fangrui Song050229d2018-11-24 00:14:31 +00005071 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
5072 AddTemplateOverloadCandidate(
5073 FTD, DeclAccessPair::make(FTD, C->getAccess()),
5074 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
5075 /*SuppressUsedConversions=*/false,
Hans Wennborgd2b9fc82019-05-06 09:51:10 +00005076 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005077 }
5078 }
5079
5080 SmallVector<ResultCandidate, 8> Results;
5081 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005082 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00005083}
5084
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00005085QualType Sema::ProduceCtorInitMemberSignatureHelp(
5086 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
5087 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
5088 if (!CodeCompleter)
5089 return QualType();
5090
5091 CXXConstructorDecl *Constructor =
5092 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
5093 if (!Constructor)
5094 return QualType();
5095 // FIXME: Add support for Base class constructors as well.
5096 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
5097 Constructor->getParent(), SS, TemplateTypeTy, II))
5098 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
5099 MemberDecl->getLocation(), ArgExprs,
5100 OpenParLoc);
5101 return QualType();
5102}
5103
John McCall48871652010-08-21 09:40:31 +00005104void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
5105 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005106 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005107 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005108 return;
5109 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005110
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005111 CodeCompleteExpressionData Data;
5112 Data.PreferredType = VD->getType();
5113 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5114 Data.IgnoreDecls.push_back(VD);
5115
5116 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005117}
5118
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005119void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005120 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005121 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005122 mapCodeCompletionContext(*this, PCC_Statement));
5123 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5124 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005125
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005126 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5127 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005128 CodeCompleter->includeGlobals(),
5129 CodeCompleter->loadExternal());
5130
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005131 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005132
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005133 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005134 CodeCompletionBuilder Builder(Results.getAllocator(),
5135 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005136 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005137 if (Results.includeCodePatterns()) {
5138 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5139 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5140 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5141 Builder.AddPlaceholderChunk("statements");
5142 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5143 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5144 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005145 Results.AddResult(Builder.TakeString());
5146
5147 // "else if" block
5148 Builder.AddTypedTextChunk("else");
5149 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5150 Builder.AddTextChunk("if");
5151 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5152 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005153 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005154 Builder.AddPlaceholderChunk("condition");
5155 else
5156 Builder.AddPlaceholderChunk("expression");
5157 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005158 if (Results.includeCodePatterns()) {
5159 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5160 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5161 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5162 Builder.AddPlaceholderChunk("statements");
5163 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5164 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5165 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005166 Results.AddResult(Builder.TakeString());
5167
5168 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005169
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005170 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005171 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005172
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005173 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005174 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005175
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005176 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005177 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005178}
5179
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005180void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005181 bool EnteringContext, QualType BaseType) {
Eric Liu06d34022017-12-12 11:35:46 +00005182 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005183 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005184
Eric Liu06d34022017-12-12 11:35:46 +00005185 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5186 // "a::b::" is not corresponding to any context/namespace in the AST), since
5187 // it can be useful for global code completion which have information about
5188 // contexts/symbols that are not in the AST.
5189 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005190 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00005191 CC.setCXXScopeSpecifier(SS);
Eric Liu206740e2019-02-21 11:22:58 +00005192 // As SS is invalid, we try to collect accessible contexts from the current
5193 // scope with a dummy lookup so that the completion consumer can try to
5194 // guess what the specified scope is.
5195 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5196 CodeCompleter->getCodeCompletionTUInfo(), CC);
5197 if (S->getEntity()) {
5198 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5199 BaseType);
5200 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5201 /*IncludeGlobalScope=*/false,
5202 /*LoadExternal=*/false);
5203 }
5204 HandleCodeCompleteResults(this, CodeCompleter,
5205 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005206 return;
5207 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005208 // Always pretend to enter a context to ensure that a dependent type
5209 // resolves to a dependent record.
5210 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005211 if (!Ctx)
5212 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005213
5214 // Try to instantiate any non-dependent declaration contexts before
5215 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005216 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005217 return;
5218
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005219 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005220 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005221 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005222 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005223
Douglas Gregor3545ff42009-09-21 16:56:56 +00005224 // The "template" keyword can follow "::" in the grammar, but only
5225 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005226 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005227 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005228 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005229
5230 // Add calls to overridden virtual functions, if there are any.
5231 //
5232 // FIXME: This isn't wonderful, because we don't know whether we're actually
5233 // in a context that permits expressions. This is a general issue with
5234 // qualified-id completions.
5235 if (!EnteringContext)
5236 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005237 Results.ExitScope();
5238
Eric Liufead6ae2017-12-13 10:26:49 +00005239 if (CodeCompleter->includeNamespaceLevelDecls() ||
5240 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005241 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005242 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5243 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005244 /*IncludeDependentBases=*/true,
5245 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005246 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005247
Eric Liu06d34022017-12-12 11:35:46 +00005248 auto CC = Results.getCompletionContext();
5249 CC.setCXXScopeSpecifier(SS);
5250
5251 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
5252 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005253}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005254
5255void Sema::CodeCompleteUsing(Scope *S) {
5256 if (!CodeCompleter)
5257 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005258
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005259 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005260 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005261 // This can be both a using alias or using
5262 // declaration, in the former we expect a new name and a
5263 // symbol in the latter case.
5264 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005265 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005266 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005267
Douglas Gregor3545ff42009-09-21 16:56:56 +00005268 // If we aren't in class scope, we could see the "namespace" keyword.
5269 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005270 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005271
5272 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005273 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005274 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005275 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005276 CodeCompleter->includeGlobals(),
5277 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005278 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005279
5280 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5281 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005282}
5283
5284void Sema::CodeCompleteUsingDirective(Scope *S) {
5285 if (!CodeCompleter)
5286 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005287
Douglas Gregor3545ff42009-09-21 16:56:56 +00005288 // After "using namespace", we expect to see a namespace name or namespace
5289 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005290 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005291 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005292 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005293 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005294 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005295 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005296 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005297 CodeCompleter->includeGlobals(),
5298 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005299 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005300 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5301 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005302}
5303
Fangrui Song050229d2018-11-24 00:14:31 +00005304void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005305 if (!CodeCompleter)
5306 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005307
Ted Kremenekc37877d2013-10-08 17:08:03 +00005308 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005309 if (!S->getParent())
5310 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005311
Fangrui Song050229d2018-11-24 00:14:31 +00005312 bool SuppressedGlobalResults =
5313 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005314
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005315 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005316 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005317 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005318 ? CodeCompletionContext::CCC_Namespace
5319 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005320 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005321
Douglas Gregor0ac41382010-09-23 23:01:17 +00005322 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005323 // We only want to see those namespaces that have already been defined
5324 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005325 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005326 // definition of each namespace.
5327 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005328 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005329 NS(Ctx->decls_begin()),
5330 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005331 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005332 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005333
5334 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005335 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005336 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005337 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005338 NS = OrigToLatest.begin(),
5339 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005340 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005341 Results.AddResult(
5342 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5343 nullptr),
5344 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005345 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005346 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005347
Fangrui Song050229d2018-11-24 00:14:31 +00005348 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5349 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005350}
5351
Fangrui Song050229d2018-11-24 00:14:31 +00005352void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005353 if (!CodeCompleter)
5354 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005355
Douglas Gregor3545ff42009-09-21 16:56:56 +00005356 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005357 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005358 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005359 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005360 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005361 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005362 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005363 CodeCompleter->includeGlobals(),
5364 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005365 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5366 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005367}
5368
Douglas Gregorc811ede2009-09-18 20:05:18 +00005369void Sema::CodeCompleteOperatorName(Scope *S) {
5370 if (!CodeCompleter)
5371 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005372
John McCall276321a2010-08-25 06:19:51 +00005373 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005374 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005375 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005376 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005377 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005378 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005379
Douglas Gregor3545ff42009-09-21 16:56:56 +00005380 // Add the names of overloadable operators.
Fangrui Song050229d2018-11-24 00:14:31 +00005381#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5382 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005383 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005384#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005385
Douglas Gregor3545ff42009-09-21 16:56:56 +00005386 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005387 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005388 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005389 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005390 CodeCompleter->includeGlobals(),
5391 CodeCompleter->loadExternal());
5392
Douglas Gregor3545ff42009-09-21 16:56:56 +00005393 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005394 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005395 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005396
5397 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5398 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005399}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005400
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005401void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005402 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005403 if (!ConstructorD)
5404 return;
5405
5406 AdjustDeclIfTemplate(ConstructorD);
5407
Fangrui Song050229d2018-11-24 00:14:31 +00005408 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005409 if (!Constructor)
5410 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005411
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005412 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005413 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005414 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005415 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005416
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005417 // Fill in any already-initialized fields or base classes.
5418 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5419 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005420 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005421 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005422 InitializedBases.insert(Context.getCanonicalType(
5423 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005424 else
Fangrui Song050229d2018-11-24 00:14:31 +00005425 InitializedFields.insert(
5426 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005427 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005428
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005429 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005430 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005431 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005432 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005433
5434 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5435 CodeCompletionBuilder Builder(Results.getAllocator(),
5436 Results.getCodeCompletionTUInfo());
5437 Builder.AddTypedTextChunk(Name);
5438 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005439 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005440 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005441 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005442 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5443 Builder);
5444 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5445 return Builder.TakeString();
5446 };
5447 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5448 const NamedDecl *ND) {
5449 CodeCompletionBuilder Builder(Results.getAllocator(),
5450 Results.getCodeCompletionTUInfo());
5451 Builder.AddTypedTextChunk(Name);
5452 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5453 Builder.AddPlaceholderChunk(Type);
5454 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5455 if (ND) {
5456 auto CCR = CodeCompletionResult(
5457 Builder.TakeString(), ND,
5458 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5459 if (isa<FieldDecl>(ND))
5460 CCR.CursorKind = CXCursor_MemberRef;
5461 return Results.AddResult(CCR);
5462 }
5463 return Results.AddResult(CodeCompletionResult(
5464 Builder.TakeString(),
5465 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5466 };
5467 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5468 const char *Name, const FieldDecl *FD) {
5469 if (!RD)
5470 return AddDefaultCtorInit(Name,
5471 FD ? Results.getAllocator().CopyString(
5472 FD->getType().getAsString(Policy))
5473 : Name,
5474 FD);
5475 auto Ctors = getConstructors(Context, RD);
5476 if (Ctors.begin() == Ctors.end())
5477 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005478 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005479 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5480 CCR.CursorKind = getCursorKindForDecl(Ctor);
5481 Results.AddResult(CCR);
5482 }
5483 };
5484 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5485 const char *BaseName =
5486 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5487 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5488 AddCtorsWithName(
5489 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5490 BaseName, nullptr);
5491 };
5492 auto AddField = [&](const FieldDecl *FD) {
5493 const char *FieldName =
5494 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5495 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5496 AddCtorsWithName(
5497 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5498 FieldName, FD);
5499 };
5500
Aaron Ballman574705e2014-03-13 15:41:46 +00005501 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005502 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5503 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005504 SawLastInitializer =
5505 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5506 Context.hasSameUnqualifiedType(
5507 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005508 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005509 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005510
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005511 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005512 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005513 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005514
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005515 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005516 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005517 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5518 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005519 SawLastInitializer =
5520 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5521 Context.hasSameUnqualifiedType(
5522 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005523 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005524 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005525
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005526 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005527 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005528 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005529
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005530 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005531 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005532 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5533 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005534 SawLastInitializer = !Initializers.empty() &&
5535 Initializers.back()->isAnyMemberInitializer() &&
5536 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005537 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005538 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005539
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005540 if (!Field->getDeclName())
5541 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005542
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005543 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005544 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005545 }
5546 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005547
Douglas Gregor0ac41382010-09-23 23:01:17 +00005548 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005549 Results.data(), Results.size());
5550}
5551
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005552/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005553static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005554 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005555 if (!DC)
5556 return false;
5557
5558 return DC->isFileContext();
5559}
5560
5561void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5562 bool AfterAmpersand) {
5563 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005564 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005565 CodeCompletionContext::CCC_Other);
5566 Results.EnterNewScope();
5567
5568 // Note what has already been captured.
5569 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5570 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005571 for (const auto &C : Intro.Captures) {
5572 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005573 IncludedThis = true;
5574 continue;
5575 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005576
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005577 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005578 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005579
Douglas Gregord8c61782012-02-15 15:34:24 +00005580 // Look for other capturable variables.
5581 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005582 for (const auto *D : S->decls()) {
5583 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005584 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005585 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005586
David Blaikie82e95a32014-11-19 07:49:47 +00005587 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005588 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005589 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005590 }
5591 }
5592
5593 // Add 'this', if it would be valid.
5594 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5595 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005596
Douglas Gregord8c61782012-02-15 15:34:24 +00005597 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005598
Douglas Gregord8c61782012-02-15 15:34:24 +00005599 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5600 Results.data(), Results.size());
5601}
5602
James Dennett596e4752012-06-14 03:11:41 +00005603/// Macro that optionally prepends an "@" to the string literal passed in via
5604/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005605#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005606
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005607static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005608 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005609 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005610 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005611 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005612
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005613 CodeCompletionBuilder Builder(Results.getAllocator(),
5614 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005615 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005616 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005617 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005618 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5619 Builder.AddPlaceholderChunk("property");
5620 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005621
Douglas Gregorf1934162010-01-13 21:24:21 +00005622 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005623 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005624 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5625 Builder.AddPlaceholderChunk("property");
5626 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005627 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005628}
5629
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005630static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005631 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005632 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005633
Douglas Gregorf1934162010-01-13 21:24:21 +00005634 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005635 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005636
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005637 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005638 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005639 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005640
Douglas Gregorf1934162010-01-13 21:24:21 +00005641 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005642 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005643
Douglas Gregorf1934162010-01-13 21:24:21 +00005644 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005645 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005646 }
5647}
5648
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005649static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005650 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005651 CodeCompletionBuilder Builder(Results.getAllocator(),
5652 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005653
Douglas Gregorf1934162010-01-13 21:24:21 +00005654 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005655 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005656 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5657 Builder.AddPlaceholderChunk("name");
5658 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005659
Douglas Gregorf4c33342010-05-28 00:22:41 +00005660 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005661 // @interface name
5662 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005663 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005664 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005665 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5666 Builder.AddPlaceholderChunk("class");
5667 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005668
Douglas Gregorf4c33342010-05-28 00:22:41 +00005669 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005670 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005671 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5672 Builder.AddPlaceholderChunk("protocol");
5673 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005674
Douglas Gregorf4c33342010-05-28 00:22:41 +00005675 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005676 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005677 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5678 Builder.AddPlaceholderChunk("class");
5679 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005680 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005681
Douglas Gregorf1934162010-01-13 21:24:21 +00005682 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005683 Builder.AddTypedTextChunk(
5684 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005685 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5686 Builder.AddPlaceholderChunk("alias");
5687 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5688 Builder.AddPlaceholderChunk("class");
5689 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005690
5691 if (Results.getSema().getLangOpts().Modules) {
5692 // @import name
5693 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5694 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5695 Builder.AddPlaceholderChunk("module");
5696 Results.AddResult(Result(Builder.TakeString()));
5697 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005698}
5699
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005700void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005701 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005702 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005703 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005704 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005705 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005706 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005707 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005708 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005709 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005710 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005711 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005712 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5713 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005714}
5715
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005716static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005717 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005718 CodeCompletionBuilder Builder(Results.getAllocator(),
5719 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005720
5721 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005722 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005723 if (Results.getSema().getLangOpts().CPlusPlus ||
5724 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005725 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005726 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005727 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005728 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5729 Builder.AddPlaceholderChunk("type-name");
5730 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5731 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005732
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005733 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005734 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005735 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005736 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5737 Builder.AddPlaceholderChunk("protocol-name");
5738 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5739 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005740
5741 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005742 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005743 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005744 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5745 Builder.AddPlaceholderChunk("selector");
5746 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5747 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005748
5749 // @"string"
5750 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005751 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005752 Builder.AddPlaceholderChunk("string");
5753 Builder.AddTextChunk("\"");
5754 Results.AddResult(Result(Builder.TakeString()));
5755
Douglas Gregor951de302012-07-17 23:24:47 +00005756 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005757 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005758 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005759 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005760 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5761 Results.AddResult(Result(Builder.TakeString()));
5762
Douglas Gregor951de302012-07-17 23:24:47 +00005763 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005764 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005765 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005766 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005767 Builder.AddChunk(CodeCompletionString::CK_Colon);
5768 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5769 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005770 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5771 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005772
Douglas Gregor951de302012-07-17 23:24:47 +00005773 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005774 Builder.AddResultTypeChunk("id");
5775 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005776 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005777 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5778 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005779}
5780
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005781static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005782 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005783 CodeCompletionBuilder Builder(Results.getAllocator(),
5784 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005785
Douglas Gregorf4c33342010-05-28 00:22:41 +00005786 if (Results.includeCodePatterns()) {
5787 // @try { statements } @catch ( declaration ) { statements } @finally
5788 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005789 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005790 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5791 Builder.AddPlaceholderChunk("statements");
5792 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5793 Builder.AddTextChunk("@catch");
5794 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5795 Builder.AddPlaceholderChunk("parameter");
5796 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5797 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5798 Builder.AddPlaceholderChunk("statements");
5799 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5800 Builder.AddTextChunk("@finally");
5801 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5802 Builder.AddPlaceholderChunk("statements");
5803 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5804 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005805 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005806
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005807 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005808 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005809 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5810 Builder.AddPlaceholderChunk("expression");
5811 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005812
Douglas Gregorf4c33342010-05-28 00:22:41 +00005813 if (Results.includeCodePatterns()) {
5814 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005815 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005816 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5817 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5818 Builder.AddPlaceholderChunk("expression");
5819 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5820 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5821 Builder.AddPlaceholderChunk("statements");
5822 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5823 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005824 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005825}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005826
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005827static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005828 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005829 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005830 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5831 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5832 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005833 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005834 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005835}
5836
5837void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005838 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005839 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005840 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005841 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005842 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005843 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005844 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5845 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005846}
5847
5848void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005849 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005850 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005851 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005852 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005853 AddObjCStatementResults(Results, false);
5854 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005855 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005856 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5857 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005858}
5859
5860void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005861 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005862 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005863 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005864 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005865 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005866 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005867 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5868 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005869}
5870
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005871/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005872/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005873static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005874 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005875 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005876 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005877
Bill Wendling44426052012-12-20 19:22:21 +00005878 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005879
Douglas Gregore6078da2009-11-19 00:14:45 +00005880 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005881 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5882 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005883 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005884
Jordan Rose53cb2f32012-08-20 20:01:13 +00005885 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00005886 unsigned AssignCopyRetMask =
5887 Attributes &
5888 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
5889 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
5890 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
5891 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005892 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005893 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005894 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005895 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5896 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005897 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005898
Douglas Gregore6078da2009-11-19 00:14:45 +00005899 return false;
5900}
5901
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005902void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005903 if (!CodeCompleter)
5904 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005905
Bill Wendling44426052012-12-20 19:22:21 +00005906 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005907
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005908 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005909 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005910 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005911 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005912 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005913 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005914 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005915 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005916 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005917 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5918 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005919 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005920 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005921 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005922 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005923 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005924 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005925 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005926 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005927 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005928 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005929 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005930 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005931
5932 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005933 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005934 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005935 Results.AddResult(CodeCompletionResult("weak"));
5936
Bill Wendling44426052012-12-20 19:22:21 +00005937 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005938 CodeCompletionBuilder Setter(Results.getAllocator(),
5939 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005940 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005941 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005942 Setter.AddPlaceholderChunk("method");
5943 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005944 }
Bill Wendling44426052012-12-20 19:22:21 +00005945 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005946 CodeCompletionBuilder Getter(Results.getAllocator(),
5947 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005948 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005949 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005950 Getter.AddPlaceholderChunk("method");
5951 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005952 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005953 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5954 Results.AddResult(CodeCompletionResult("nonnull"));
5955 Results.AddResult(CodeCompletionResult("nullable"));
5956 Results.AddResult(CodeCompletionResult("null_unspecified"));
5957 Results.AddResult(CodeCompletionResult("null_resettable"));
5958 }
Steve Naroff936354c2009-10-08 21:55:05 +00005959 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005960 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5961 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005962}
Steve Naroffeae65032009-11-07 02:08:14 +00005963
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005964/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005965/// via code completion.
5966enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005967 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5968 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00005969 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005970};
5971
Fangrui Song050229d2018-11-24 00:14:31 +00005972static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005973 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005974 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005975 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005976 if (NumSelIdents > Sel.getNumArgs())
5977 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005978
Douglas Gregor67c692c2010-08-26 15:07:07 +00005979 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00005980 case MK_Any:
5981 break;
5982 case MK_ZeroArgSelector:
5983 return Sel.isUnarySelector();
5984 case MK_OneArgSelector:
5985 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005986 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005987
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005988 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5989 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005990
Douglas Gregor67c692c2010-08-26 15:07:07 +00005991 for (unsigned I = 0; I != NumSelIdents; ++I)
5992 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5993 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005994
Douglas Gregor67c692c2010-08-26 15:07:07 +00005995 return true;
5996}
5997
Douglas Gregorc8537c52009-11-19 07:41:15 +00005998static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5999 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006000 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006001 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006002 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006003 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006004}
Douglas Gregor1154e272010-09-16 16:06:31 +00006005
Fangrui Song050229d2018-11-24 00:14:31 +00006006/// A set of selectors, which is used to avoid introducing multiple
6007/// completions with the same selector into the result set.
6008typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00006009
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006010/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006011/// container to the set of results.
6012///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006013/// The container will be a class, protocol, category, or implementation of
6014/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006015/// the superclasses of classes along with their categories, protocols, and
6016/// implementations.
6017///
6018/// \param Container the container in which we'll look to find methods.
6019///
James Dennett596e4752012-06-14 03:11:41 +00006020/// \param WantInstanceMethods Whether to add instance methods (only); if
6021/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006022///
6023/// \param CurContext the context in which we're performing the lookup that
6024/// finds methods.
6025///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006026/// \param AllowSameLength Whether we allow a method to be added to the list
6027/// when it has the same number of parameters as we have selector identifiers.
6028///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006029/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006030static void AddObjCMethods(ObjCContainerDecl *Container,
6031 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006032 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006033 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006034 VisitedSelectorSet &Selectors, bool AllowSameLength,
6035 ResultBuilder &Results, bool InOriginalClass = true,
6036 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00006037 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006038 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00006039 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00006040 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00006041 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00006042 // The instance methods on the root class can be messaged via the
6043 // metaclass.
6044 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00006045 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006046 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00006047 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006048 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00006049 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00006050
David Blaikie82e95a32014-11-19 07:49:47 +00006051 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006052 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006053
6054 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006055 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00006056 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00006057 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00006058 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00006059 Results.MaybeAddResult(R, CurContext);
6060 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006061 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006062
Douglas Gregorf37c9492010-09-16 15:34:59 +00006063 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006064 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00006065 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006066 const ObjCList<ObjCProtocolDecl> &Protocols =
6067 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006068 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006069 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006070 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006071 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6072 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00006073 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00006074 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006075
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006076 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006077 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006078
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006079 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006080 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006081 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6082 Selectors, AllowSameLength, Results, false, IsRootClass);
6083
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006084 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00006085 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006086 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006087 CurContext, Selectors, AllowSameLength, Results,
6088 InOriginalClass, IsRootClass);
6089
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006090 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00006091 const ObjCList<ObjCProtocolDecl> &Protocols =
6092 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006093 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6094 E = Protocols.end();
6095 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006096 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6097 Selectors, AllowSameLength, Results, false, IsRootClass);
6098
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006099 // Add methods in category implementations.
6100 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006101 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6102 Selectors, AllowSameLength, Results, InOriginalClass,
6103 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006104 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006105
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006106 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006107 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006108 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006109 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6110 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6111 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006112
6113 // Add methods in our implementation, if any.
6114 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006115 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6116 Selectors, AllowSameLength, Results, InOriginalClass,
6117 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006118}
6119
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006120void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006121 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006122 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006123 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006124 if (ObjCCategoryDecl *Category =
6125 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006126 Class = Category->getClassInterface();
6127
6128 if (!Class)
6129 return;
6130 }
6131
6132 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006133 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006134 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006135 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006136 Results.EnterNewScope();
6137
Douglas Gregor1154e272010-09-16 16:06:31 +00006138 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006139 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006140 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006141 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006142 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6143 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006144}
6145
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006146void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006147 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006148 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006149 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006150 if (ObjCCategoryDecl *Category =
6151 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006152 Class = Category->getClassInterface();
6153
6154 if (!Class)
6155 return;
6156 }
6157
6158 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006159 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006160 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006161 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006162 Results.EnterNewScope();
6163
Douglas Gregor1154e272010-09-16 16:06:31 +00006164 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006165 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6166 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006167
6168 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006169 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6170 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006171}
6172
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006173void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6174 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006175 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006176 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006177 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006178 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006179
Douglas Gregor99fa2642010-08-24 01:06:58 +00006180 // Add context-sensitive, Objective-C parameter-passing keywords.
6181 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006182 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006183 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6184 Results.AddResult("in");
6185 Results.AddResult("inout");
6186 AddedInOut = true;
6187 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006188 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006189 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6190 Results.AddResult("out");
6191 if (!AddedInOut)
6192 Results.AddResult("inout");
6193 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006194 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006195 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6196 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006197 Results.AddResult("bycopy");
6198 Results.AddResult("byref");
6199 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006200 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006201 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6202 Results.AddResult("nonnull");
6203 Results.AddResult("nullable");
6204 Results.AddResult("null_unspecified");
6205 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006206
6207 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006208 // identifier IBAction refers to a macro, provide a completion item for
6209 // an action, e.g.,
6210 // IBAction)<#selector#>:(id)sender
6211 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006212 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006213 CodeCompletionBuilder Builder(Results.getAllocator(),
6214 Results.getCodeCompletionTUInfo(),
6215 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006216 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006217 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006218 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006219 Builder.AddChunk(CodeCompletionString::CK_Colon);
6220 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006221 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006222 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006223 Builder.AddTextChunk("sender");
6224 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6225 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006226
6227 // If we're completing the return type, provide 'instancetype'.
6228 if (!IsParameter) {
6229 Results.AddResult(CodeCompletionResult("instancetype"));
6230 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006231
Douglas Gregor99fa2642010-08-24 01:06:58 +00006232 // Add various builtin type names and specifiers.
6233 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6234 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006235
Douglas Gregor99fa2642010-08-24 01:06:58 +00006236 // Add the various type names
6237 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6238 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6239 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006240 CodeCompleter->includeGlobals(),
6241 CodeCompleter->loadExternal());
6242
Douglas Gregor99fa2642010-08-24 01:06:58 +00006243 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006244 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006245
Eric Liuf5ba09f2018-07-04 10:01:18 +00006246 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006247 Results.data(), Results.size());
6248}
6249
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006250/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006251/// that it has some more-specific class type based on knowledge of
6252/// common uses of Objective-C. This routine returns that class type,
6253/// or NULL if no better result could be determined.
6254static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006255 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006256 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006257 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006258
6259 Selector Sel = Msg->getSelector();
6260 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006261 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006262
6263 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6264 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006265 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006266
6267 ObjCMethodDecl *Method = Msg->getMethodDecl();
6268 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006269 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006270
6271 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006272 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006273 switch (Msg->getReceiverKind()) {
6274 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006275 if (const ObjCObjectType *ObjType =
6276 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006277 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006278 break;
6279
6280 case ObjCMessageExpr::Instance: {
6281 QualType T = Msg->getInstanceReceiver()->getType();
6282 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6283 IFace = Ptr->getInterfaceDecl();
6284 break;
6285 }
6286
6287 case ObjCMessageExpr::SuperInstance:
6288 case ObjCMessageExpr::SuperClass:
6289 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006290 }
6291
6292 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006293 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006294
6295 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6296 if (Method->isInstanceMethod())
6297 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006298 .Case("retain", IFace)
6299 .Case("strong", IFace)
6300 .Case("autorelease", IFace)
6301 .Case("copy", IFace)
6302 .Case("copyWithZone", IFace)
6303 .Case("mutableCopy", IFace)
6304 .Case("mutableCopyWithZone", IFace)
6305 .Case("awakeFromCoder", IFace)
6306 .Case("replacementObjectFromCoder", IFace)
6307 .Case("class", IFace)
6308 .Case("classForCoder", IFace)
6309 .Case("superclass", Super)
6310 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006311
6312 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006313 .Case("new", IFace)
6314 .Case("alloc", IFace)
6315 .Case("allocWithZone", IFace)
6316 .Case("class", IFace)
6317 .Case("superclass", Super)
6318 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006319}
6320
Douglas Gregor6fc04132010-08-27 15:10:57 +00006321// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006322// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006323// function.
6324///
6325/// \param S The semantic analysis object.
6326///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006327/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006328/// the "super" keyword. Otherwise, we just need to provide the arguments.
6329///
6330/// \param SelIdents The identifiers in the selector that have already been
6331/// provided as arguments for a send to "super".
6332///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006333/// \param Results The set of results to augment.
6334///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006335/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006336/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006337static ObjCMethodDecl *
6338AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6339 ArrayRef<IdentifierInfo *> SelIdents,
6340 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006341 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6342 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006343 return nullptr;
6344
Douglas Gregor6fc04132010-08-27 15:10:57 +00006345 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6346 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006347 return nullptr;
6348
Douglas Gregor6fc04132010-08-27 15:10:57 +00006349 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006350 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006351 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6352 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006353 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006354 CurMethod->isInstanceMethod());
6355
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006356 // Check in categories or class extensions.
6357 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006358 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006359 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006360 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006361 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006362 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006363 }
6364 }
6365
Douglas Gregor6fc04132010-08-27 15:10:57 +00006366 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006367 return nullptr;
6368
Douglas Gregor6fc04132010-08-27 15:10:57 +00006369 // Check whether the superclass method has the same signature.
6370 if (CurMethod->param_size() != SuperMethod->param_size() ||
6371 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006372 return nullptr;
6373
Douglas Gregor6fc04132010-08-27 15:10:57 +00006374 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006375 CurPEnd = CurMethod->param_end(),
6376 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006377 CurP != CurPEnd; ++CurP, ++SuperP) {
6378 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006379 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006380 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006381 return nullptr;
6382
Douglas Gregor6fc04132010-08-27 15:10:57 +00006383 // Make sure we have a parameter name to forward!
6384 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006385 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006386 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006387
Douglas Gregor6fc04132010-08-27 15:10:57 +00006388 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006389 CodeCompletionBuilder Builder(Results.getAllocator(),
6390 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006391
Douglas Gregor6fc04132010-08-27 15:10:57 +00006392 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006393 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006394 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006395
6396 // If we need the "super" keyword, add it (plus some spacing).
6397 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006398 Builder.AddTypedTextChunk("super");
6399 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006400 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006401
Douglas Gregor6fc04132010-08-27 15:10:57 +00006402 Selector Sel = CurMethod->getSelector();
6403 if (Sel.isUnarySelector()) {
6404 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006405 Builder.AddTextChunk(
6406 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006407 else
Fangrui Song050229d2018-11-24 00:14:31 +00006408 Builder.AddTypedTextChunk(
6409 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006410 } else {
6411 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6412 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006413 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006414 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006415
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006416 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006417 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006418 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006419 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006420 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006421 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006422 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006423 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006424 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006425 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006426 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006427 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006428 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006429 }
6430 }
6431 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006432
Douglas Gregor78254c82012-03-27 23:34:16 +00006433 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6434 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006435 return SuperMethod;
6436}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006437
Douglas Gregora817a192010-05-27 23:06:34 +00006438void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006439 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006440 ResultBuilder Results(
6441 *this, CodeCompleter->getAllocator(),
6442 CodeCompleter->getCodeCompletionTUInfo(),
6443 CodeCompletionContext::CCC_ObjCMessageReceiver,
6444 getLangOpts().CPlusPlus11
6445 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6446 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006447
Douglas Gregora817a192010-05-27 23:06:34 +00006448 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6449 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006450 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006451 CodeCompleter->includeGlobals(),
6452 CodeCompleter->loadExternal());
6453
Douglas Gregora817a192010-05-27 23:06:34 +00006454 // If we are in an Objective-C method inside a class that has a superclass,
6455 // add "super" as an option.
6456 if (ObjCMethodDecl *Method = getCurMethodDecl())
6457 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006458 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006459 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006460
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006461 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006462 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006463
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006464 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006465 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006466
Douglas Gregora817a192010-05-27 23:06:34 +00006467 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006468
Douglas Gregora817a192010-05-27 23:06:34 +00006469 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006470 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006471 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006472 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006473}
6474
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006475void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006476 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006477 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006478 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006479 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6480 // Figure out which interface we're in.
6481 CDecl = CurMethod->getClassInterface();
6482 if (!CDecl)
6483 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006484
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006485 // Find the superclass of this class.
6486 CDecl = CDecl->getSuperClass();
6487 if (!CDecl)
6488 return;
6489
6490 if (CurMethod->isInstanceMethod()) {
6491 // We are inside an instance method, which means that the message
6492 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006493 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006494 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006495 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006496 }
6497
6498 // Fall through to send to the superclass in CDecl.
6499 } else {
6500 // "super" may be the name of a type or variable. Figure out which
6501 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006502 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006503 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006504 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6505 // "super" names an interface. Use it.
6506 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006507 if (const ObjCObjectType *Iface =
6508 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006509 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006510 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6511 // "super" names an unresolved type; we can't be more specific.
6512 } else {
6513 // Assume that "super" names some kind of value and parse that way.
6514 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006515 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006516 UnqualifiedId id;
6517 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006518 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6519 /*HasTrailingLParen=*/false,
6520 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006521 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006522 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006523 }
6524
6525 // Fall through
6526 }
6527
John McCallba7bf592010-08-24 05:47:05 +00006528 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006529 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006530 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006531 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006532 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006533 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006534}
6535
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006536/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006537/// send, determine the preferred type (if any) for that argument expression.
6538static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6539 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006540 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006541 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006542
Douglas Gregor74661272010-09-21 00:03:25 +00006543 QualType PreferredType;
6544 unsigned BestPriority = CCP_Unlikely * 2;
6545 Result *ResultsData = Results.data();
6546 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6547 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006548 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006549 isa<ObjCMethodDecl>(R.Declaration)) {
6550 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006551 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006552 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006553 QualType MyPreferredType =
6554 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006555 if (R.Priority < BestPriority || PreferredType.isNull()) {
6556 BestPriority = R.Priority;
6557 PreferredType = MyPreferredType;
6558 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6559 MyPreferredType)) {
6560 PreferredType = QualType();
6561 }
6562 }
6563 }
6564 }
6565 }
6566
6567 return PreferredType;
6568}
6569
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006570static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006571 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006572 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006573 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006574 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006575 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006576 ObjCInterfaceDecl *CDecl = nullptr;
6577
Douglas Gregor8ce33212009-11-17 17:59:40 +00006578 // If the given name refers to an interface type, retrieve the
6579 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006580 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006581 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006582 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006583 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6584 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006585 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006586
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006587 // Add all of the factory methods in this Objective-C class, its protocols,
6588 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006589 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006590
6591 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006592 // completion.
6593 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006594 if (ObjCMethodDecl *SuperMethod =
6595 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006596 Results.Ignore(SuperMethod);
6597 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006598
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006599 // If we're inside an Objective-C method definition, prefer its selector to
6600 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006601 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006602 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006603
Douglas Gregor1154e272010-09-16 16:06:31 +00006604 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006605 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006606 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6607 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006608 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006609 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006610
Douglas Gregord720daf2010-04-06 17:30:22 +00006611 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006612 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006613 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006614 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006615 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006616 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006617 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006618 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006619 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006620
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006621 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006622 }
6623 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006624
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006625 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006626 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006627 M != MEnd; ++M) {
6628 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006629 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006630 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006631 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006632
Nico Weber2e0c8f72014-12-27 03:58:08 +00006633 Result R(MethList->getMethod(),
6634 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006635 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006636 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006637 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006638 }
6639 }
6640 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006641
6642 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006643}
Douglas Gregor6285f752010-04-06 16:40:00 +00006644
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006645void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006646 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006647 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006648 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006649
Douglas Gregor63745d52011-07-21 01:05:26 +00006650 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006651
Fangrui Song050229d2018-11-24 00:14:31 +00006652 ResultBuilder Results(
6653 *this, CodeCompleter->getAllocator(),
6654 CodeCompleter->getCodeCompletionTUInfo(),
6655 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6656 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006657
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006658 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006659 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006660
6661 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006662 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006663 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006664 // code-complete the expression using the corresponding parameter type as
6665 // our preferred type, improving completion results.
6666 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006667 QualType PreferredType =
6668 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006669 if (PreferredType.isNull())
6670 CodeCompleteOrdinaryName(S, PCC_Expression);
6671 else
6672 CodeCompleteExpression(S, PreferredType);
6673 return;
6674 }
6675
Fangrui Song050229d2018-11-24 00:14:31 +00006676 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006677 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006678}
6679
Richard Trieu2bd04012011-09-09 02:00:50 +00006680void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006681 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006682 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006683 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006684 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006685
Steve Naroffeae65032009-11-07 02:08:14 +00006686 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006687
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006688 // If necessary, apply function/array conversion to the receiver.
6689 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006690 if (RecExpr) {
6691 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6692 if (Conv.isInvalid()) // conversion failed. bail.
6693 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006694 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006695 }
Fangrui Song050229d2018-11-24 00:14:31 +00006696 QualType ReceiverType = RecExpr
6697 ? RecExpr->getType()
6698 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006699 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006700 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006701
Douglas Gregordc520b02010-11-08 21:12:30 +00006702 // If we're messaging an expression with type "id" or "Class", check
6703 // whether we know something special about the receiver that allows
6704 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006705 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006706 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6707 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006708 return CodeCompleteObjCClassMessage(
6709 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6710 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006711
Fangrui Song050229d2018-11-24 00:14:31 +00006712 ReceiverType =
6713 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006714 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006715 } else if (RecExpr && getLangOpts().CPlusPlus) {
6716 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6717 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006718 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006719 ReceiverType = RecExpr->getType();
6720 }
6721 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006722
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006723 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006724 ResultBuilder Results(
6725 *this, CodeCompleter->getAllocator(),
6726 CodeCompleter->getCodeCompletionTUInfo(),
6727 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6728 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006729
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006730 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006731
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006732 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006733 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006734 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006735 if (ObjCMethodDecl *SuperMethod =
6736 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006737 Results.Ignore(SuperMethod);
6738 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006739
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006740 // If we're inside an Objective-C method definition, prefer its selector to
6741 // others.
6742 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6743 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006744
Douglas Gregor1154e272010-09-16 16:06:31 +00006745 // Keep track of the selectors we've already added.
6746 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006747
Douglas Gregora3329fa2009-11-18 00:06:18 +00006748 // Handle messages to Class. This really isn't a message to an instance
6749 // method, so we treat it the same way we would treat a message send to a
6750 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006751 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006752 ReceiverType->isObjCQualifiedClassType()) {
6753 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6754 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006755 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6756 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006757 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006758 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006759 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006760 else if (const ObjCObjectPointerType *QualID =
6761 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006762 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006763 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006764 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6765 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006766 }
6767 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006768 else if (const ObjCObjectPointerType *IFacePtr =
6769 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006770 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006771 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006772 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006773
Douglas Gregora3329fa2009-11-18 00:06:18 +00006774 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006775 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006776 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6777 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006778 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006779 // Handle messages to "id".
6780 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006781 // We're messaging "id", so provide all instance methods we know
6782 // about as code-completion results.
6783
6784 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006785 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006786 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006787 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6788 I != N; ++I) {
6789 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006790 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006791 continue;
6792
Sebastian Redl75d8a322010-08-02 23:18:59 +00006793 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006794 }
6795 }
6796
Sebastian Redl75d8a322010-08-02 23:18:59 +00006797 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6798 MEnd = MethodPool.end();
6799 M != MEnd; ++M) {
6800 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006801 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006802 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006803 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006804
Nico Weber2e0c8f72014-12-27 03:58:08 +00006805 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006806 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006807
Nico Weber2e0c8f72014-12-27 03:58:08 +00006808 Result R(MethList->getMethod(),
6809 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006810 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006811 R.AllParametersAreInformative = false;
6812 Results.MaybeAddResult(R, CurContext);
6813 }
6814 }
6815 }
Steve Naroffeae65032009-11-07 02:08:14 +00006816 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006817
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006818 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006819 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006820 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006821 // code-complete the expression using the corresponding parameter type as
6822 // our preferred type, improving completion results.
6823 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006824 QualType PreferredType =
6825 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006826 if (PreferredType.isNull())
6827 CodeCompleteOrdinaryName(S, PCC_Expression);
6828 else
6829 CodeCompleteExpression(S, PreferredType);
6830 return;
6831 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006832
Fangrui Song050229d2018-11-24 00:14:31 +00006833 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6834 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006835}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006836
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006837void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006838 DeclGroupPtrTy IterationVar) {
6839 CodeCompleteExpressionData Data;
6840 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006841
Douglas Gregor68762e72010-08-23 21:17:50 +00006842 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006843 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006844 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6845 if (*I)
6846 Data.IgnoreDecls.push_back(*I);
6847 }
6848 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006849
Douglas Gregor68762e72010-08-23 21:17:50 +00006850 CodeCompleteExpression(S, Data);
6851}
6852
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006853void Sema::CodeCompleteObjCSelector(Scope *S,
6854 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006855 // If we have an external source, load the entire class method
6856 // pool from the AST file.
6857 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00006858 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
6859 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006860 Selector Sel = ExternalSource->GetExternalSelector(I);
6861 if (Sel.isNull() || MethodPool.count(Sel))
6862 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006863
Douglas Gregor67c692c2010-08-26 15:07:07 +00006864 ReadMethodPool(Sel);
6865 }
6866 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006867
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006868 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006869 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006870 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006871 Results.EnterNewScope();
6872 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006873 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006874 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006875
Douglas Gregor67c692c2010-08-26 15:07:07 +00006876 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006877 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006878 continue;
6879
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006880 CodeCompletionBuilder Builder(Results.getAllocator(),
6881 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006882 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006883 Builder.AddTypedTextChunk(
6884 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006885 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006886 continue;
6887 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006888
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006889 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006890 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006891 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006892 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006893 Builder.AddInformativeChunk(
6894 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006895 Accumulator.clear();
6896 }
6897 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006898
Benjamin Kramer632500c2011-07-26 16:59:25 +00006899 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006900 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006901 }
Fangrui Song050229d2018-11-24 00:14:31 +00006902 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006903 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006904 }
6905 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006906
6907 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006908 Results.data(), Results.size());
6909}
6910
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006911/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006912/// (translation unit) context.
6913static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006914 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006915 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006916 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006917
Aaron Ballman629afae2014-03-07 19:56:05 +00006918 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006919 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006920 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006921 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00006922 Results.AddResult(
6923 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
6924 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006925 }
6926}
6927
Craig Topper883dd332015-12-24 23:58:11 +00006928void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00006929 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006930 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006931 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006932 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006933
Chandler Carruthede11632016-11-04 06:06:50 +00006934 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006935 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006936
Douglas Gregora3b23b02010-12-09 21:44:02 +00006937 // Tell the result set to ignore all of the protocols we have
6938 // already seen.
6939 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006940 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00006941 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006942 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006943
Douglas Gregora3b23b02010-12-09 21:44:02 +00006944 // Add all protocols.
6945 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6946 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006947
Douglas Gregora3b23b02010-12-09 21:44:02 +00006948 Results.ExitScope();
6949 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006950
6951 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6952 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006953}
6954
6955void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006956 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006957 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006958 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006959
Chandler Carruthede11632016-11-04 06:06:50 +00006960 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006961 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006962
Douglas Gregora3b23b02010-12-09 21:44:02 +00006963 // Add all protocols.
6964 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6965 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006966
Douglas Gregora3b23b02010-12-09 21:44:02 +00006967 Results.ExitScope();
6968 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006969
6970 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6971 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006972}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006973
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006974/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006975/// the given (translation unit) context.
6976static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6977 bool OnlyForwardDeclarations,
6978 bool OnlyUnimplemented,
6979 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006980 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006981
Aaron Ballman629afae2014-03-07 19:56:05 +00006982 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006983 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006984 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006985 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006986 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00006987 Results.AddResult(
6988 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
6989 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006990 }
6991}
6992
Eric Liuf5ba09f2018-07-04 10:01:18 +00006993void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006995 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006996 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006997 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006998
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006999 if (CodeCompleter->includeGlobals()) {
7000 // Add all classes.
7001 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7002 false, Results);
7003 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007004
Douglas Gregor49c22a72009-11-18 16:26:39 +00007005 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007006
Eric Liuf5ba09f2018-07-04 10:01:18 +00007007 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7008 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007009}
7010
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007011void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007012 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007013 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007014 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007015 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007016 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007017
Douglas Gregor49c22a72009-11-18 16:26:39 +00007018 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00007019 NamedDecl *CurClass =
7020 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007021 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00007022 Results.Ignore(CurClass);
7023
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007024 if (CodeCompleter->includeGlobals()) {
7025 // Add all classes.
7026 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7027 false, Results);
7028 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007029
Douglas Gregor49c22a72009-11-18 16:26:39 +00007030 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007031
Eric Liuf5ba09f2018-07-04 10:01:18 +00007032 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7033 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007034}
7035
Eric Liuf5ba09f2018-07-04 10:01:18 +00007036void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007037 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007038 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007039 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007040 Results.EnterNewScope();
7041
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007042 if (CodeCompleter->includeGlobals()) {
7043 // Add all unimplemented classes.
7044 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7045 true, Results);
7046 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007047
Douglas Gregor49c22a72009-11-18 16:26:39 +00007048 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007049
Eric Liuf5ba09f2018-07-04 10:01:18 +00007050 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7051 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007052}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007053
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007054void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007055 IdentifierInfo *ClassName,
7056 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007057 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007058
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007059 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007060 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007061 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007062
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007063 // Ignore any categories we find that have already been implemented by this
7064 // interface.
7065 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00007066 NamedDecl *CurClass =
7067 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
7068 if (ObjCInterfaceDecl *Class =
7069 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007070 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007071 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007072 }
7073
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007074 // Add all of the categories we know about.
7075 Results.EnterNewScope();
7076 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007077 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00007078 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00007079 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00007080 Results.AddResult(
7081 Result(Category, Results.getBasePriority(Category), nullptr),
7082 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007083 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007084
7085 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7086 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007087}
7088
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007089void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007090 IdentifierInfo *ClassName,
7091 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007092 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007093
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007094 // Find the corresponding interface. If we couldn't find the interface, the
7095 // program itself is ill-formed. However, we'll try to be helpful still by
7096 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00007097 NamedDecl *CurClass =
7098 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007099 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
7100 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007101 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007102
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007103 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007104 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007105 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007106
7107 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007108 // declarations in this class and any of its superclasses, except for
7109 // already-implemented categories in the class itself.
7110 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7111 Results.EnterNewScope();
7112 bool IgnoreImplemented = true;
7113 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007114 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007115 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007116 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007117 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7118 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007119 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007120
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007121 Class = Class->getSuperClass();
7122 IgnoreImplemented = false;
7123 }
7124 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007125
7126 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7127 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007128}
Douglas Gregor5d649882009-11-18 22:32:06 +00007129
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007130void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007131 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007132 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007133 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007134
7135 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007136 ObjCContainerDecl *Container =
7137 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7138 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7139 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007140 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007141
7142 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007143 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007144 for (const auto *D : Container->decls())
7145 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007146 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007147
Douglas Gregor5d649882009-11-18 22:32:06 +00007148 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007149 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007150 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007151 if (ObjCImplementationDecl *ClassImpl =
7152 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007153 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007154 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007155 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007156 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007157 AddObjCProperties(CCContext,
7158 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007159 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007160 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007161 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007162
7163 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7164 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007165}
7166
Fangrui Song050229d2018-11-24 00:14:31 +00007167void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7168 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007169 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007170 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007171 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007172 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007173
7174 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007175 ObjCContainerDecl *Container =
7176 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7177 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7178 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007179 return;
7180
Douglas Gregor5d649882009-11-18 22:32:06 +00007181 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007182 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007183 if (ObjCImplementationDecl *ClassImpl =
7184 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007185 Class = ClassImpl->getClassInterface();
7186 else
Fangrui Song050229d2018-11-24 00:14:31 +00007187 Class = cast<ObjCCategoryImplDecl>(Container)
7188 ->getCategoryDecl()
7189 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007190
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007191 // Determine the type of the property we're synthesizing.
7192 QualType PropertyType = Context.getObjCIdType();
7193 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007194 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7195 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007196 PropertyType =
7197 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007198
7199 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007200 Results.setPreferredType(PropertyType);
7201 }
7202 }
7203
Douglas Gregor5d649882009-11-18 22:32:06 +00007204 // Add all of the instance variables in this class and its superclasses.
7205 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007206 bool SawSimilarlyNamedIvar = false;
7207 std::string NameWithPrefix;
7208 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007209 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007210 std::string NameWithSuffix = PropertyName->getName().str();
7211 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007212 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007213 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007214 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007215 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7216 CurContext, nullptr, false);
7217
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007218 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007219 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007220 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007221 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007222 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007223 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007224
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007225 // Reduce the priority of this result by one, to give it a slight
7226 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007227 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007228 Results.data()[Results.size() - 1].Kind ==
7229 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007230 Results.data()[Results.size() - 1].Declaration == Ivar)
7231 Results.data()[Results.size() - 1].Priority--;
7232 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007233 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007234 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007235
Douglas Gregor331faa02011-04-18 14:13:53 +00007236 if (!SawSimilarlyNamedIvar) {
7237 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007238 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007239 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007240 typedef CodeCompletionResult Result;
7241 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007242 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007243 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007244
Douglas Gregor75acd922011-09-27 23:30:47 +00007245 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007246 Builder.AddResultTypeChunk(
7247 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007248 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007249 Results.AddResult(
7250 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007251 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007252
Douglas Gregor5d649882009-11-18 22:32:06 +00007253 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007254
7255 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7256 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007257}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007258
Douglas Gregor416b5752010-08-25 01:08:01 +00007259// Mapping from selectors to the methods that implement that selector, along
7260// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007261typedef llvm::DenseMap<Selector,
7262 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7263 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007264
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007265/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007266/// (and its superclasses, protocols, etc.) that meet the given
7267/// criteria. Insert those methods into the map of known methods,
7268/// indexed by selector so they can be easily found.
7269static void FindImplementableMethods(ASTContext &Context,
7270 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007271 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007272 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007273 KnownMethodsMap &KnownMethods,
7274 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007275 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007276 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007277 if (!IFace->hasDefinition())
7278 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007279
7280 IFace = IFace->getDefinition();
7281 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007282
Fangrui Song050229d2018-11-24 00:14:31 +00007283 const ObjCList<ObjCProtocolDecl> &Protocols =
7284 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007285 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007286 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007287 I != E; ++I)
7288 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007289 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007290
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007291 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007292 for (auto *Cat : IFace->visible_categories()) {
7293 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007294 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007295 }
7296
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007297 // Visit the superclass.
7298 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007299 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007300 WantInstanceMethods, ReturnType, KnownMethods,
7301 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007302 }
7303
7304 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7305 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007306 const ObjCList<ObjCProtocolDecl> &Protocols =
7307 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007308 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007309 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007310 I != E; ++I)
7311 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007312 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007313
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007314 // If this category is the original class, jump to the interface.
7315 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007316 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007317 WantInstanceMethods, ReturnType, KnownMethods,
7318 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007319 }
7320
7321 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007322 // Make sure we have a definition; that's what we'll walk.
7323 if (!Protocol->hasDefinition())
7324 return;
7325 Protocol = Protocol->getDefinition();
7326 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007327
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007328 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007329 const ObjCList<ObjCProtocolDecl> &Protocols =
7330 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007331 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007332 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007333 I != E; ++I)
7334 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7335 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007336 }
7337
7338 // Add methods in this container. This operation occurs last because
7339 // we want the methods from this container to override any methods
7340 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007341 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007342 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007343 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007344 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007345 continue;
7346
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007347 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007348 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007349 }
7350 }
7351}
7352
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007353/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007354/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007355static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007356 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007357 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007358 CodeCompletionBuilder &Builder) {
7359 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007360 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007361 if (!Quals.empty())
7362 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007363 Builder.AddTextChunk(
7364 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007365 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7366}
7367
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007368/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007369/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007370static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007371 if (!Class)
7372 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007373
Douglas Gregor669a25a2011-02-17 00:22:45 +00007374 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7375 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007376
Douglas Gregor669a25a2011-02-17 00:22:45 +00007377 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7378}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007379
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007380/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007381/// Key-Value Observing (KVO).
7382static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7383 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007384 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007385 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007386 ResultBuilder &Results) {
7387 IdentifierInfo *PropName = Property->getIdentifier();
7388 if (!PropName || PropName->getLength() == 0)
7389 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007390
Douglas Gregor75acd922011-09-27 23:30:47 +00007391 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7392
Douglas Gregor669a25a2011-02-17 00:22:45 +00007393 // Builder that will create each code completion.
7394 typedef CodeCompletionResult Result;
7395 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007396 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007397
Douglas Gregor669a25a2011-02-17 00:22:45 +00007398 // The selector table.
7399 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007400
Douglas Gregor669a25a2011-02-17 00:22:45 +00007401 // The property name, copied into the code completion allocation region
7402 // on demand.
7403 struct KeyHolder {
7404 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007405 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007406 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007407
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007408 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007409 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007410
Douglas Gregor669a25a2011-02-17 00:22:45 +00007411 operator const char *() {
7412 if (CopiedKey)
7413 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007414
Douglas Gregor669a25a2011-02-17 00:22:45 +00007415 return CopiedKey = Allocator.CopyString(Key);
7416 }
7417 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007418
Douglas Gregor669a25a2011-02-17 00:22:45 +00007419 // The uppercased name of the property name.
7420 std::string UpperKey = PropName->getName();
7421 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007422 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007423
Fangrui Song050229d2018-11-24 00:14:31 +00007424 bool ReturnTypeMatchesProperty =
7425 ReturnType.isNull() ||
7426 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7427 Property->getType());
7428 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007429
Douglas Gregor669a25a2011-02-17 00:22:45 +00007430 // Add the normal accessor -(type)key.
7431 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007432 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007433 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7434 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007435 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7436 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007437
Douglas Gregor669a25a2011-02-17 00:22:45 +00007438 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007439 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007440 CXCursor_ObjCInstanceMethodDecl));
7441 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007442
Douglas Gregor669a25a2011-02-17 00:22:45 +00007443 // If we have an integral or boolean property (or the user has provided
7444 // an integral or boolean return type), add the accessor -(type)isKey.
7445 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007446 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007447 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007448 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7449 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007450 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007451 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007452 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7453 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007454 if (ReturnType.isNull()) {
7455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7456 Builder.AddTextChunk("BOOL");
7457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7458 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007459
Fangrui Song050229d2018-11-24 00:14:31 +00007460 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007461 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007462 CXCursor_ObjCInstanceMethodDecl));
7463 }
7464 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007465
Douglas Gregor669a25a2011-02-17 00:22:45 +00007466 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007467 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007468 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007469 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007470 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007471 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007472 if (ReturnType.isNull()) {
7473 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7474 Builder.AddTextChunk("void");
7475 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7476 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007477
Fangrui Song050229d2018-11-24 00:14:31 +00007478 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007479 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007480 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7481 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007482 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007483 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007484 CXCursor_ObjCInstanceMethodDecl));
7485 }
7486 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007487
Douglas Gregor669a25a2011-02-17 00:22:45 +00007488 // Indexed and unordered accessors
7489 unsigned IndexedGetterPriority = CCP_CodePattern;
7490 unsigned IndexedSetterPriority = CCP_CodePattern;
7491 unsigned UnorderedGetterPriority = CCP_CodePattern;
7492 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007493 if (const auto *ObjCPointer =
7494 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007495 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7496 // If this interface type is not provably derived from a known
7497 // collection, penalize the corresponding completions.
7498 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007499 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007500 if (!InheritsFromClassNamed(IFace, "NSArray"))
7501 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7502 }
7503
7504 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007505 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007506 if (!InheritsFromClassNamed(IFace, "NSSet"))
7507 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7508 }
7509 }
7510 } else {
7511 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7512 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7513 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7514 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7515 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007516
Douglas Gregor669a25a2011-02-17 00:22:45 +00007517 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007518 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007519 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007520 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007521 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007522 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7523 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007524 if (ReturnType.isNull()) {
7525 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7526 Builder.AddTextChunk("NSUInteger");
7527 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7528 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007529
Fangrui Song050229d2018-11-24 00:14:31 +00007530 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7531 Results.AddResult(
7532 Result(Builder.TakeString(),
7533 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7534 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007535 }
7536 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007537
Douglas Gregor669a25a2011-02-17 00:22:45 +00007538 // Indexed getters
7539 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7540 if (IsInstanceMethod &&
7541 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007542 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007543 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007544 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007545 if (ReturnType.isNull()) {
7546 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7547 Builder.AddTextChunk("id");
7548 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7549 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007550
Douglas Gregor669a25a2011-02-17 00:22:45 +00007551 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7552 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7553 Builder.AddTextChunk("NSUInteger");
7554 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7555 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007556 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007557 CXCursor_ObjCInstanceMethodDecl));
7558 }
7559 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007560
Douglas Gregor669a25a2011-02-17 00:22:45 +00007561 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7562 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007563 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007564 (ReturnType->isObjCObjectPointerType() &&
7565 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007566 ReturnType->getAs<ObjCObjectPointerType>()
7567 ->getInterfaceDecl()
7568 ->getName() == "NSArray"))) {
7569 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007570 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007571 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 if (ReturnType.isNull()) {
7573 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7574 Builder.AddTextChunk("NSArray *");
7575 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7576 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007577
Douglas Gregor669a25a2011-02-17 00:22:45 +00007578 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7579 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7580 Builder.AddTextChunk("NSIndexSet *");
7581 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7582 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007583 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007584 CXCursor_ObjCInstanceMethodDecl));
7585 }
7586 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007587
Douglas Gregor669a25a2011-02-17 00:22:45 +00007588 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7589 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007590 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007591 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7592 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007593
David Blaikie82e95a32014-11-19 07:49:47 +00007594 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007595 if (ReturnType.isNull()) {
7596 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7597 Builder.AddTextChunk("void");
7598 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7599 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007600
Douglas Gregor669a25a2011-02-17 00:22:45 +00007601 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7602 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7603 Builder.AddPlaceholderChunk("object-type");
7604 Builder.AddTextChunk(" **");
7605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7606 Builder.AddTextChunk("buffer");
7607 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7608 Builder.AddTypedTextChunk("range:");
7609 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7610 Builder.AddTextChunk("NSRange");
7611 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7612 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007613 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007614 CXCursor_ObjCInstanceMethodDecl));
7615 }
7616 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007617
Douglas Gregor669a25a2011-02-17 00:22:45 +00007618 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007619
Douglas Gregor669a25a2011-02-17 00:22:45 +00007620 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7621 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007622 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007623 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7624 &Context.Idents.get(SelectorName)};
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("insertObject:");
7634 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7635 Builder.AddPlaceholderChunk("object-type");
7636 Builder.AddTextChunk(" *");
7637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7638 Builder.AddTextChunk("object");
7639 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7640 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7641 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7642 Builder.AddPlaceholderChunk("NSUInteger");
7643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7644 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007645 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007646 CXCursor_ObjCInstanceMethodDecl));
7647 }
7648 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007649
Douglas Gregor669a25a2011-02-17 00:22:45 +00007650 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7651 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007652 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007653 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7654 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007655
David Blaikie82e95a32014-11-19 07:49:47 +00007656 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007657 if (ReturnType.isNull()) {
7658 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7659 Builder.AddTextChunk("void");
7660 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7661 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007662
Douglas Gregor669a25a2011-02-17 00:22:45 +00007663 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7664 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7665 Builder.AddTextChunk("NSArray *");
7666 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7667 Builder.AddTextChunk("array");
7668 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7669 Builder.AddTypedTextChunk("atIndexes:");
7670 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7671 Builder.AddPlaceholderChunk("NSIndexSet *");
7672 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7673 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007674 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007675 CXCursor_ObjCInstanceMethodDecl));
7676 }
7677 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007678
Douglas Gregor669a25a2011-02-17 00:22:45 +00007679 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7680 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007681 std::string SelectorName =
7682 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007683 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007684 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007685 if (ReturnType.isNull()) {
7686 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7687 Builder.AddTextChunk("void");
7688 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7689 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007690
Douglas Gregor669a25a2011-02-17 00:22:45 +00007691 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7692 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7693 Builder.AddTextChunk("NSUInteger");
7694 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7695 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007696 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007697 CXCursor_ObjCInstanceMethodDecl));
7698 }
7699 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007700
Douglas Gregor669a25a2011-02-17 00:22:45 +00007701 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7702 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007703 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007704 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007705 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007706 if (ReturnType.isNull()) {
7707 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7708 Builder.AddTextChunk("void");
7709 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7710 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007711
Douglas Gregor669a25a2011-02-17 00:22:45 +00007712 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7713 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7714 Builder.AddTextChunk("NSIndexSet *");
7715 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7716 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007717 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007718 CXCursor_ObjCInstanceMethodDecl));
7719 }
7720 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007721
Douglas Gregor669a25a2011-02-17 00:22:45 +00007722 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7723 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007724 std::string SelectorName =
7725 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7726 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7727 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007728
David Blaikie82e95a32014-11-19 07:49:47 +00007729 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007730 if (ReturnType.isNull()) {
7731 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7732 Builder.AddTextChunk("void");
7733 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7734 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007735
Douglas Gregor669a25a2011-02-17 00:22:45 +00007736 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7737 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7738 Builder.AddPlaceholderChunk("NSUInteger");
7739 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7740 Builder.AddTextChunk("index");
7741 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7742 Builder.AddTypedTextChunk("withObject:");
7743 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7744 Builder.AddTextChunk("id");
7745 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7746 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007747 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007748 CXCursor_ObjCInstanceMethodDecl));
7749 }
7750 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007751
Douglas Gregor669a25a2011-02-17 00:22:45 +00007752 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7753 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007754 std::string SelectorName1 =
7755 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007756 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007757 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7758 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007759
David Blaikie82e95a32014-11-19 07:49:47 +00007760 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007761 if (ReturnType.isNull()) {
7762 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7763 Builder.AddTextChunk("void");
7764 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7765 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007766
Douglas Gregor669a25a2011-02-17 00:22:45 +00007767 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7768 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7769 Builder.AddPlaceholderChunk("NSIndexSet *");
7770 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7771 Builder.AddTextChunk("indexes");
7772 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7773 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7774 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7775 Builder.AddTextChunk("NSArray *");
7776 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7777 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007778 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007779 CXCursor_ObjCInstanceMethodDecl));
7780 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007781 }
7782
Douglas Gregor669a25a2011-02-17 00:22:45 +00007783 // Unordered getters
7784 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007785 if (IsInstanceMethod &&
7786 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007787 (ReturnType->isObjCObjectPointerType() &&
7788 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007789 ReturnType->getAs<ObjCObjectPointerType>()
7790 ->getInterfaceDecl()
7791 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007792 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007793 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007794 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7795 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007796 if (ReturnType.isNull()) {
7797 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7798 Builder.AddTextChunk("NSEnumerator *");
7799 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7800 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007801
Douglas Gregor669a25a2011-02-17 00:22:45 +00007802 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007803 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007804 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007805 }
7806 }
7807
7808 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007809 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007810 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007811 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007812 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007813 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007814 if (ReturnType.isNull()) {
7815 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7816 Builder.AddPlaceholderChunk("object-type");
7817 Builder.AddTextChunk(" *");
7818 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7819 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007820
Douglas Gregor669a25a2011-02-17 00:22:45 +00007821 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7822 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7823 if (ReturnType.isNull()) {
7824 Builder.AddPlaceholderChunk("object-type");
7825 Builder.AddTextChunk(" *");
7826 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007827 Builder.AddTextChunk(GetCompletionTypeString(
7828 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007829 }
7830 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7831 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007832 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007833 CXCursor_ObjCInstanceMethodDecl));
7834 }
7835 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007836
Douglas Gregor669a25a2011-02-17 00:22:45 +00007837 // Mutable unordered accessors
7838 // - (void)addKeyObject:(type *)object
7839 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007840 std::string SelectorName =
7841 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007842 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007843 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007844 if (ReturnType.isNull()) {
7845 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7846 Builder.AddTextChunk("void");
7847 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7848 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007849
Douglas Gregor669a25a2011-02-17 00:22:45 +00007850 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7852 Builder.AddPlaceholderChunk("object-type");
7853 Builder.AddTextChunk(" *");
7854 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7855 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007856 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007857 CXCursor_ObjCInstanceMethodDecl));
7858 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007859 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007860
7861 // - (void)addKey:(NSSet *)objects
7862 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007863 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007864 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007865 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007866 if (ReturnType.isNull()) {
7867 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7868 Builder.AddTextChunk("void");
7869 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7870 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007871
Douglas Gregor669a25a2011-02-17 00:22:45 +00007872 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7873 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7874 Builder.AddTextChunk("NSSet *");
7875 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7876 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007877 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007878 CXCursor_ObjCInstanceMethodDecl));
7879 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007880 }
7881
Douglas Gregor669a25a2011-02-17 00:22:45 +00007882 // - (void)removeKeyObject:(type *)object
7883 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007884 std::string SelectorName =
7885 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007886 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007887 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007888 if (ReturnType.isNull()) {
7889 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7890 Builder.AddTextChunk("void");
7891 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7892 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007893
Douglas Gregor669a25a2011-02-17 00:22:45 +00007894 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7895 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7896 Builder.AddPlaceholderChunk("object-type");
7897 Builder.AddTextChunk(" *");
7898 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7899 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007900 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007901 CXCursor_ObjCInstanceMethodDecl));
7902 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007903 }
7904
Douglas Gregor669a25a2011-02-17 00:22:45 +00007905 // - (void)removeKey:(NSSet *)objects
7906 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007907 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007908 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007909 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007910 if (ReturnType.isNull()) {
7911 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7912 Builder.AddTextChunk("void");
7913 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7914 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007915
Douglas Gregor669a25a2011-02-17 00:22:45 +00007916 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7917 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7918 Builder.AddTextChunk("NSSet *");
7919 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7920 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007921 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007922 CXCursor_ObjCInstanceMethodDecl));
7923 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007924 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007925
7926 // - (void)intersectKey:(NSSet *)objects
7927 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007928 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007929 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007930 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007931 if (ReturnType.isNull()) {
7932 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7933 Builder.AddTextChunk("void");
7934 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7935 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007936
Douglas Gregor669a25a2011-02-17 00:22:45 +00007937 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7938 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7939 Builder.AddTextChunk("NSSet *");
7940 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7941 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007942 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007943 CXCursor_ObjCInstanceMethodDecl));
7944 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007945 }
7946
Douglas Gregor669a25a2011-02-17 00:22:45 +00007947 // Key-Value Observing
7948 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007949 if (!IsInstanceMethod &&
7950 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007951 (ReturnType->isObjCObjectPointerType() &&
7952 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007953 ReturnType->getAs<ObjCObjectPointerType>()
7954 ->getInterfaceDecl()
7955 ->getName() == "NSSet"))) {
7956 std::string SelectorName =
7957 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007958 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007959 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7960 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007961 if (ReturnType.isNull()) {
7962 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007963 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007964 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7965 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007966
Douglas Gregor669a25a2011-02-17 00:22:45 +00007967 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007968 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007969 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00007970 }
7971 }
7972
7973 // + (BOOL)automaticallyNotifiesObserversForKey
7974 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00007975 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007976 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007977 std::string SelectorName =
7978 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007979 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007980 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7981 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007982 if (ReturnType.isNull()) {
7983 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7984 Builder.AddTextChunk("BOOL");
7985 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7986 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007987
Douglas Gregor857bcda2011-06-02 04:02:27 +00007988 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007989 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007990 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007991 }
7992 }
7993}
7994
Alex Lorenzb8740422017-10-24 16:39:37 +00007995void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007996 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007997 // Determine the return type of the method we're declaring, if
7998 // provided.
7999 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00008000 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008001 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00008002 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
8003 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008004 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008005 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00008006 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00008007 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00008008 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008009 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
8010 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008011 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00008012 } else if (ObjCCategoryImplDecl *CatImpl =
8013 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008014 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008015 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008016 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00008017 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008018 }
8019
8020 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00008021 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00008022 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008023 }
8024
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008025 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008026 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008027 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008028 return;
8029 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008030
Douglas Gregor636a61e2010-04-07 00:21:17 +00008031 // Find all of the methods that we could declare/implement here.
8032 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00008033 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
8034 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008035
Douglas Gregor636a61e2010-04-07 00:21:17 +00008036 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00008037 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008038 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008039 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008040 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008041 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00008042 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008043 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008044 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008045 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008046 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008047 CodeCompletionBuilder Builder(Results.getAllocator(),
8048 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00008049
8050 // Add the '-'/'+' prefix if it wasn't provided yet.
8051 if (!IsInstanceMethod) {
8052 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
8053 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8054 }
8055
Douglas Gregor636a61e2010-04-07 00:21:17 +00008056 // If the result type was not already provided, add it to the
8057 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008058 if (ReturnType.isNull()) {
8059 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
8060 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00008061 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
8062 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008063 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008064
8065 Selector Sel = Method->getSelector();
8066
8067 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00008068 Builder.AddTypedTextChunk(
8069 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008070
8071 // Add parameters to the pattern.
8072 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008073 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008074 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008075 P != PEnd; (void)++P, ++I) {
8076 // Add the part of the selector name.
8077 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008078 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00008079 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008080 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8081 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00008082 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008083 } else
8084 break;
8085
8086 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00008087 QualType ParamType;
8088 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
8089 ParamType = (*P)->getType();
8090 else
8091 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00008092 ParamType = ParamType.substObjCTypeArgs(
8093 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008094 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00008095 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
8096 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008097
Douglas Gregor636a61e2010-04-07 00:21:17 +00008098 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00008099 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008100 }
8101
8102 if (Method->isVariadic()) {
8103 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008104 Builder.AddChunk(CodeCompletionString::CK_Comma);
8105 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008106 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008107
Douglas Gregord37c59d2010-05-28 00:57:46 +00008108 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008109 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008110 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8111 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8112 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008113 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008114 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008115 Builder.AddTextChunk("return");
8116 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8117 Builder.AddPlaceholderChunk("expression");
8118 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008119 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008120 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008121
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008122 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8123 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008124 }
8125
Douglas Gregor416b5752010-08-25 01:08:01 +00008126 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008127 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008128 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008129 setInBaseClass(R);
8130 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008131 }
8132
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008133 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008134 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008135 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008136 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008137 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008138
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008139 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008140 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008141 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008142 M != MEnd; ++M)
8143 KnownSelectors.insert(M->first);
8144
Douglas Gregor669a25a2011-02-17 00:22:45 +00008145 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8146 if (!IFace)
8147 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8148 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008149
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008150 if (IFace)
8151 for (auto *Cat : IFace->visible_categories())
8152 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008153
8154 if (IsInstanceMethod) {
8155 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8156 for (auto *P : Containers[I]->instance_properties())
8157 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8158 KnownSelectors, Results);
8159 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008160 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008161
Douglas Gregor636a61e2010-04-07 00:21:17 +00008162 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008163
8164 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8165 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008166}
Douglas Gregor95887f92010-07-08 23:20:03 +00008167
Fangrui Song050229d2018-11-24 00:14:31 +00008168void Sema::CodeCompleteObjCMethodDeclSelector(
8169 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8170 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008171 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008172 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008173 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008174 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8175 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008176 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008177 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008178 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008179
8180 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008181 }
8182 }
8183
8184 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008185 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008186 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008187 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008188 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008189
Douglas Gregor95887f92010-07-08 23:20:03 +00008190 if (ReturnTy)
8191 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008192
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008193 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008194 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8195 MEnd = MethodPool.end();
8196 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008197 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8198 : &M->second.second;
8199 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008200 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008201 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008202
Douglas Gregor45879692010-07-08 23:37:41 +00008203 if (AtParameterName) {
8204 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008205 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008206 if (NumSelIdents &&
8207 NumSelIdents <= MethList->getMethod()->param_size()) {
8208 ParmVarDecl *Param =
8209 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008210 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008211 CodeCompletionBuilder Builder(Results.getAllocator(),
8212 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008213 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008214 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008215 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008216 }
8217 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008218
Douglas Gregor45879692010-07-08 23:37:41 +00008219 continue;
8220 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008221
Nico Weber2e0c8f72014-12-27 03:58:08 +00008222 Result R(MethList->getMethod(),
8223 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008224 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008225 R.AllParametersAreInformative = false;
8226 R.DeclaringEntity = true;
8227 Results.MaybeAddResult(R, CurContext);
8228 }
8229 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008230
Douglas Gregor95887f92010-07-08 23:20:03 +00008231 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008232
8233 if (!AtParameterName && !SelIdents.empty() &&
8234 SelIdents.front()->getName().startswith("init")) {
8235 for (const auto &M : PP.macros()) {
8236 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8237 continue;
8238 Results.EnterNewScope();
8239 CodeCompletionBuilder Builder(Results.getAllocator(),
8240 Results.getCodeCompletionTUInfo());
8241 Builder.AddTypedTextChunk(
8242 Builder.getAllocator().CopyString(M.first->getName()));
8243 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8244 CXCursor_MacroDefinition));
8245 Results.ExitScope();
8246 }
8247 }
8248
Eric Liuf5ba09f2018-07-04 10:01:18 +00008249 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8250 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008251}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008252
Douglas Gregorec00a262010-08-24 22:20:20 +00008253void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008254 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008255 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008256 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008257 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008258
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008259 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008260 CodeCompletionBuilder Builder(Results.getAllocator(),
8261 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008262 Builder.AddTypedTextChunk("if");
8263 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8264 Builder.AddPlaceholderChunk("condition");
8265 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008266
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008267 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008268 Builder.AddTypedTextChunk("ifdef");
8269 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8270 Builder.AddPlaceholderChunk("macro");
8271 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008272
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008273 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008274 Builder.AddTypedTextChunk("ifndef");
8275 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8276 Builder.AddPlaceholderChunk("macro");
8277 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008278
8279 if (InConditional) {
8280 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008281 Builder.AddTypedTextChunk("elif");
8282 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8283 Builder.AddPlaceholderChunk("condition");
8284 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008285
8286 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008287 Builder.AddTypedTextChunk("else");
8288 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008289
8290 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008291 Builder.AddTypedTextChunk("endif");
8292 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008293 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008294
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008295 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008296 Builder.AddTypedTextChunk("include");
8297 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8298 Builder.AddTextChunk("\"");
8299 Builder.AddPlaceholderChunk("header");
8300 Builder.AddTextChunk("\"");
8301 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008302
8303 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008304 Builder.AddTypedTextChunk("include");
8305 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8306 Builder.AddTextChunk("<");
8307 Builder.AddPlaceholderChunk("header");
8308 Builder.AddTextChunk(">");
8309 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008310
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008311 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008312 Builder.AddTypedTextChunk("define");
8313 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8314 Builder.AddPlaceholderChunk("macro");
8315 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008316
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008317 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008318 Builder.AddTypedTextChunk("define");
8319 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8320 Builder.AddPlaceholderChunk("macro");
8321 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8322 Builder.AddPlaceholderChunk("args");
8323 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8324 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008325
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008326 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008327 Builder.AddTypedTextChunk("undef");
8328 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8329 Builder.AddPlaceholderChunk("macro");
8330 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008331
8332 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008333 Builder.AddTypedTextChunk("line");
8334 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8335 Builder.AddPlaceholderChunk("number");
8336 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008337
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008338 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008339 Builder.AddTypedTextChunk("line");
8340 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8341 Builder.AddPlaceholderChunk("number");
8342 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8343 Builder.AddTextChunk("\"");
8344 Builder.AddPlaceholderChunk("filename");
8345 Builder.AddTextChunk("\"");
8346 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008347
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008348 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008349 Builder.AddTypedTextChunk("error");
8350 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8351 Builder.AddPlaceholderChunk("message");
8352 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008353
8354 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008355 Builder.AddTypedTextChunk("pragma");
8356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8357 Builder.AddPlaceholderChunk("arguments");
8358 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008359
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008360 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008361 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008362 Builder.AddTypedTextChunk("import");
8363 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8364 Builder.AddTextChunk("\"");
8365 Builder.AddPlaceholderChunk("header");
8366 Builder.AddTextChunk("\"");
8367 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008368
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008369 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008370 Builder.AddTypedTextChunk("import");
8371 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8372 Builder.AddTextChunk("<");
8373 Builder.AddPlaceholderChunk("header");
8374 Builder.AddTextChunk(">");
8375 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008376 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008377
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008378 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008379 Builder.AddTypedTextChunk("include_next");
8380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8381 Builder.AddTextChunk("\"");
8382 Builder.AddPlaceholderChunk("header");
8383 Builder.AddTextChunk("\"");
8384 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008385
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008386 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008387 Builder.AddTypedTextChunk("include_next");
8388 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8389 Builder.AddTextChunk("<");
8390 Builder.AddPlaceholderChunk("header");
8391 Builder.AddTextChunk(">");
8392 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008393
8394 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008395 Builder.AddTypedTextChunk("warning");
8396 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8397 Builder.AddPlaceholderChunk("message");
8398 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008399
8400 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8401 // completions for them. And __include_macros is a Clang-internal extension
8402 // that we don't want to encourage anyone to use.
8403
8404 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8405 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008406
8407 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008408 Results.data(), Results.size());
8409}
8410
8411void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008412 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8413 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008414}
8415
Douglas Gregorec00a262010-08-24 22:20:20 +00008416void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008417 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008418 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008419 IsDefinition ? CodeCompletionContext::CCC_MacroName
8420 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008421 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008422 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008423 CodeCompletionBuilder Builder(Results.getAllocator(),
8424 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008425 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008426 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008427 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008428 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008429 Builder.AddTypedTextChunk(
8430 Builder.getAllocator().CopyString(M->first->getName()));
8431 Results.AddResult(CodeCompletionResult(
8432 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008433 }
8434 Results.ExitScope();
8435 } else if (IsDefinition) {
8436 // FIXME: Can we detect when the user just wrote an include guard above?
8437 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008438
Douglas Gregor0ac41382010-09-23 23:01:17 +00008439 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008440 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008441}
8442
Douglas Gregorec00a262010-08-24 22:20:20 +00008443void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008444 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008445 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008446 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008447
Douglas Gregorec00a262010-08-24 22:20:20 +00008448 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008449 AddMacroResults(PP, Results,
8450 CodeCompleter ? CodeCompleter->loadExternal() : false,
8451 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008452
Fangrui Song050229d2018-11-24 00:14:31 +00008453 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008454 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008455 CodeCompletionBuilder Builder(Results.getAllocator(),
8456 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008457 Builder.AddTypedTextChunk("defined");
8458 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8459 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8460 Builder.AddPlaceholderChunk("macro");
8461 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8462 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008463 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008464
8465 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8466 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008467}
8468
8469void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8470 IdentifierInfo *Macro,
8471 MacroInfo *MacroInfo,
8472 unsigned Argument) {
8473 // FIXME: In the future, we could provide "overload" results, much like we
8474 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008475
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008476 // Now just ignore this. There will be another code-completion callback
8477 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008478}
8479
Sam McCall3d8051a2018-09-18 08:40:41 +00008480// This handles completion inside an #include filename, e.g. #include <foo/ba
8481// We look for the directory "foo" under each directory on the include path,
8482// list its files, and reassemble the appropriate #include.
8483void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8484 // RelDir should use /, but unescaped \ is possible on windows!
8485 // Our completions will normalize to / for simplicity, this case is rare.
8486 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8487 // We need the native slashes for the actual file system interactions.
8488 SmallString<128> NativeRelDir = StringRef(RelDir);
8489 llvm::sys::path::native(NativeRelDir);
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008490 llvm::vfs::FileSystem &FS =
8491 getSourceManager().getFileManager().getVirtualFileSystem();
Sam McCall3d8051a2018-09-18 08:40:41 +00008492
8493 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8494 CodeCompleter->getCodeCompletionTUInfo(),
8495 CodeCompletionContext::CCC_IncludedFile);
8496 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8497
8498 // Helper: adds one file or directory completion result.
8499 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8500 SmallString<64> TypedChunk = Filename;
8501 // Directory completion is up to the slash, e.g. <sys/
8502 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8503 auto R = SeenResults.insert(TypedChunk);
8504 if (R.second) { // New completion
8505 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8506 *R.first = InternedTyped; // Avoid dangling StringRef.
8507 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8508 CodeCompleter->getCodeCompletionTUInfo());
8509 Builder.AddTypedTextChunk(InternedTyped);
8510 // The result is a "Pattern", which is pretty opaque.
8511 // We may want to include the real filename to allow smart ranking.
8512 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8513 }
8514 };
8515
8516 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008517 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8518 bool IsSystem,
8519 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008520 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008521 if (!NativeRelDir.empty()) {
8522 if (LookupType == DirectoryLookup::LT_Framework) {
8523 // For a framework dir, #include <Foo/Bar/> actually maps to
8524 // a path of Foo.framework/Headers/Bar/.
8525 auto Begin = llvm::sys::path::begin(NativeRelDir);
8526 auto End = llvm::sys::path::end(NativeRelDir);
8527
8528 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8529 llvm::sys::path::append(Dir, ++Begin, End);
8530 } else {
8531 llvm::sys::path::append(Dir, NativeRelDir);
8532 }
8533 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008534
8535 std::error_code EC;
8536 unsigned Count = 0;
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008537 for (auto It = FS.dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008538 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008539 if (++Count == 2500) // If we happen to hit a huge directory,
8540 break; // bail out early so we're not too slow.
8541 StringRef Filename = llvm::sys::path::filename(It->path());
8542 switch (It->type()) {
8543 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008544 // All entries in a framework directory must have a ".framework" suffix,
8545 // but the suffix does not appear in the source code's include/import.
8546 if (LookupType == DirectoryLookup::LT_Framework &&
8547 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8548 break;
8549
Sam McCall3d8051a2018-09-18 08:40:41 +00008550 AddCompletion(Filename, /*IsDirectory=*/true);
8551 break;
8552 case llvm::sys::fs::file_type::regular_file:
8553 // Only files that really look like headers. (Except in system dirs).
8554 if (!IsSystem) {
8555 // Header extensions from Types.def, which we can't depend on here.
8556 if (!(Filename.endswith_lower(".h") ||
8557 Filename.endswith_lower(".hh") ||
8558 Filename.endswith_lower(".hpp") ||
8559 Filename.endswith_lower(".inc")))
8560 break;
8561 }
8562 AddCompletion(Filename, /*IsDirectory=*/false);
8563 break;
8564 default:
8565 break;
8566 }
8567 }
8568 };
8569
8570 // Helper: adds results relative to IncludeDir, if possible.
8571 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8572 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008573 switch (IncludeDir.getLookupType()) {
8574 case DirectoryLookup::LT_HeaderMap:
8575 // header maps are not (currently) enumerable.
8576 break;
8577 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008578 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8579 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008580 break;
8581 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008582 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8583 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008584 break;
8585 }
8586 };
8587
8588 // Finally with all our helpers, we can scan the include path.
8589 // Do this in standard order so deduplication keeps the right file.
8590 // (In case we decide to add more details to the results later).
8591 const auto &S = PP.getHeaderSearchInfo();
8592 using llvm::make_range;
8593 if (!Angled) {
8594 // The current directory is on the include path for "quoted" includes.
8595 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8596 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008597 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8598 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008599 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8600 AddFilesFromDirLookup(D, false);
8601 }
8602 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008603 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008604 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8605 AddFilesFromDirLookup(D, true);
8606
8607 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8608 Results.data(), Results.size());
8609}
8610
Douglas Gregor11583702010-08-25 17:04:25 +00008611void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008612 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008613 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8614 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008615}
8616
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008617void Sema::CodeCompleteAvailabilityPlatformName() {
8618 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8619 CodeCompleter->getCodeCompletionTUInfo(),
8620 CodeCompletionContext::CCC_Other);
8621 Results.EnterNewScope();
8622 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8623 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8624 Results.AddResult(CodeCompletionResult(Platform));
8625 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8626 Twine(Platform) + "ApplicationExtension")));
8627 }
8628 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008629 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8630 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008631}
8632
Fangrui Song050229d2018-11-24 00:14:31 +00008633void Sema::GatherGlobalCodeCompletions(
8634 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8635 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008636 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8637 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008638 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008639 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008640 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008641 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8642 Consumer,
8643 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008644 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008645
Douglas Gregorb14904c2010-08-13 22:48:40 +00008646 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008647 AddMacroResults(PP, Builder,
8648 CodeCompleter ? CodeCompleter->loadExternal() : false,
8649 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008650
Douglas Gregorb14904c2010-08-13 22:48:40 +00008651 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008652 Results.insert(Results.end(), Builder.data(),
8653 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008654}