blob: 0f2434fc0a23e50dfee9f13844f604160382d8dd [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"
Sam McCall3dea5272019-06-10 15:17:52 +000019#include "clang/AST/Type.h"
Jordan Rose4938f272013-02-09 10:09:43 +000020#include "clang/Basic/CharInfo.h"
Sam McCall3dea5272019-06-10 15:17:52 +000021#include "clang/Basic/Specifiers.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000022#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000023#include "clang/Lex/MacroInfo.h"
24#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000025#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000026#include "clang/Sema/Lookup.h"
27#include "clang/Sema/Overload.h"
28#include "clang/Sema/Scope.h"
29#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000030#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000031#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000032#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000033#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000034#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000035#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000036#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000037#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000038#include "llvm/ADT/iterator_range.h"
39#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000040#include <list>
41#include <map>
Ilya Biryukovcabab292019-05-24 10:18:39 +000042#include <string>
Douglas Gregor3545ff42009-09-21 16:56:56 +000043#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000044
45using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000046using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000047
Douglas Gregor3545ff42009-09-21 16:56:56 +000048namespace {
Fangrui Song050229d2018-11-24 00:14:31 +000049/// A container of code-completion results.
50class ResultBuilder {
51public:
52 /// The type of a name-lookup filter, which can be provided to the
53 /// name-lookup routines to specify which declarations should be included in
54 /// the result set (when it returns true) and which declarations should be
55 /// filtered out (returns false).
56 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000057
Fangrui Song050229d2018-11-24 00:14:31 +000058 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000059
Fangrui Song050229d2018-11-24 00:14:31 +000060private:
61 /// The actual results we have found.
62 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000063
Fangrui Song050229d2018-11-24 00:14:31 +000064 /// A record of all of the declarations we have found and placed
65 /// into the result set, used to ensure that no declaration ever gets into
66 /// the result set twice.
67 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000068
Fangrui Song050229d2018-11-24 00:14:31 +000069 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000070
Fangrui Song050229d2018-11-24 00:14:31 +000071 /// An entry in the shadow map, which is optimized to store
72 /// a single (declaration, index) mapping (the common case) but
73 /// can also store a list of (declaration, index) mappings.
74 class ShadowMapEntry {
75 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000076
Fangrui Song050229d2018-11-24 00:14:31 +000077 /// Contains either the solitary NamedDecl * or a vector
78 /// of (declaration, index) pairs.
79 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000080
Fangrui Song050229d2018-11-24 00:14:31 +000081 /// When the entry contains a single declaration, this is
82 /// the index associated with that entry.
83 unsigned SingleDeclIndex;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000084
Douglas Gregor3545ff42009-09-21 16:56:56 +000085 public:
Fangrui Song050229d2018-11-24 00:14:31 +000086 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
Sam McCall3dea5272019-06-10 15:17:52 +000087 ShadowMapEntry(const ShadowMapEntry &) = delete;
88 ShadowMapEntry(ShadowMapEntry &&Move) { *this = std::move(Move); }
89 ShadowMapEntry &operator=(const ShadowMapEntry &) = delete;
90 ShadowMapEntry &operator=(ShadowMapEntry &&Move) {
91 SingleDeclIndex = Move.SingleDeclIndex;
92 DeclOrVector = Move.DeclOrVector;
93 Move.DeclOrVector = nullptr;
94 return *this;
95 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000096
Fangrui Song050229d2018-11-24 00:14:31 +000097 void Add(const NamedDecl *ND, unsigned Index) {
98 if (DeclOrVector.isNull()) {
99 // 0 - > 1 elements: just set the single element information.
100 DeclOrVector = ND;
101 SingleDeclIndex = Index;
102 return;
103 }
104
105 if (const NamedDecl *PrevND =
106 DeclOrVector.dyn_cast<const NamedDecl *>()) {
107 // 1 -> 2 elements: create the vector of results and push in the
108 // existing declaration.
109 DeclIndexPairVector *Vec = new DeclIndexPairVector;
110 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
111 DeclOrVector = Vec;
112 }
113
114 // Add the new element to the end of the vector.
115 DeclOrVector.get<DeclIndexPairVector *>()->push_back(
116 DeclIndexPair(ND, Index));
117 }
118
Sam McCall3dea5272019-06-10 15:17:52 +0000119 ~ShadowMapEntry() {
Fangrui Song050229d2018-11-24 00:14:31 +0000120 if (DeclIndexPairVector *Vec =
121 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
122 delete Vec;
123 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05fcf842010-11-02 20:36:02 +0000124 }
125 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000126
Fangrui Song050229d2018-11-24 00:14:31 +0000127 // Iteration.
128 class iterator;
129 iterator begin() const;
130 iterator end() const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000131 };
Fangrui Song050229d2018-11-24 00:14:31 +0000132
133 /// A mapping from declaration names to the declarations that have
134 /// this name within a particular scope and their index within the list of
135 /// results.
136 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
137
138 /// The semantic analysis object for which results are being
139 /// produced.
140 Sema &SemaRef;
141
142 /// The allocator used to allocate new code-completion strings.
143 CodeCompletionAllocator &Allocator;
144
145 CodeCompletionTUInfo &CCTUInfo;
146
147 /// If non-NULL, a filter function used to remove any code-completion
148 /// results that are not desirable.
149 LookupFilter Filter;
150
151 /// Whether we should allow declarations as
152 /// nested-name-specifiers that would otherwise be filtered out.
153 bool AllowNestedNameSpecifiers;
154
155 /// If set, the type that we would prefer our resulting value
156 /// declarations to have.
157 ///
158 /// Closely matching the preferred type gives a boost to a result's
159 /// priority.
160 CanQualType PreferredType;
161
162 /// A list of shadow maps, which is used to model name hiding at
163 /// different levels of, e.g., the inheritance hierarchy.
164 std::list<ShadowMap> ShadowMaps;
165
Sam McCall3dea5272019-06-10 15:17:52 +0000166 /// Overloaded C++ member functions found by SemaLookup.
167 /// Used to determine when one overload is dominated by another.
168 llvm::DenseMap<std::pair<DeclContext *, /*Name*/uintptr_t>, ShadowMapEntry>
169 OverloadMap;
170
Fangrui Song050229d2018-11-24 00:14:31 +0000171 /// If we're potentially referring to a C++ member function, the set
172 /// of qualifiers applied to the object type.
173 Qualifiers ObjectTypeQualifiers;
Sam McCall3dea5272019-06-10 15:17:52 +0000174 /// The kind of the object expression, for rvalue/lvalue overloads.
175 ExprValueKind ObjectKind;
Fangrui Song050229d2018-11-24 00:14:31 +0000176
177 /// Whether the \p ObjectTypeQualifiers field is active.
178 bool HasObjectTypeQualifiers;
179
180 /// The selector that we prefer.
181 Selector PreferredSelector;
182
183 /// The completion context in which we are gathering results.
184 CodeCompletionContext CompletionContext;
185
186 /// If we are in an instance method definition, the \@implementation
187 /// object.
188 ObjCImplementationDecl *ObjCImplementation;
189
190 void AdjustResultPriorityForDecl(Result &R);
191
192 void MaybeAddConstructorResults(Result R);
193
194public:
195 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
196 CodeCompletionTUInfo &CCTUInfo,
197 const CodeCompletionContext &CompletionContext,
198 LookupFilter Filter = nullptr)
199 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
200 Filter(Filter), AllowNestedNameSpecifiers(false),
201 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
202 ObjCImplementation(nullptr) {
203 // If this is an Objective-C instance method definition, dig out the
204 // corresponding implementation.
205 switch (CompletionContext.getKind()) {
206 case CodeCompletionContext::CCC_Expression:
207 case CodeCompletionContext::CCC_ObjCMessageReceiver:
208 case CodeCompletionContext::CCC_ParenthesizedExpression:
209 case CodeCompletionContext::CCC_Statement:
210 case CodeCompletionContext::CCC_Recovery:
211 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
212 if (Method->isInstanceMethod())
213 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
214 ObjCImplementation = Interface->getImplementation();
215 break;
216
217 default:
218 break;
219 }
220 }
221
222 /// Determine the priority for a reference to the given declaration.
223 unsigned getBasePriority(const NamedDecl *D);
224
225 /// Whether we should include code patterns in the completion
226 /// results.
227 bool includeCodePatterns() const {
228 return SemaRef.CodeCompleter &&
229 SemaRef.CodeCompleter->includeCodePatterns();
230 }
231
232 /// Set the filter used for code-completion results.
233 void setFilter(LookupFilter Filter) { this->Filter = Filter; }
234
235 Result *data() { return Results.empty() ? nullptr : &Results.front(); }
236 unsigned size() const { return Results.size(); }
237 bool empty() const { return Results.empty(); }
238
239 /// Specify the preferred type.
240 void setPreferredType(QualType T) {
241 PreferredType = SemaRef.Context.getCanonicalType(T);
242 }
243
244 /// Set the cv-qualifiers on the object type, for us in filtering
245 /// calls to member functions.
246 ///
247 /// When there are qualifiers in this set, they will be used to filter
248 /// out member functions that aren't available (because there will be a
249 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
250 /// match.
Sam McCall3dea5272019-06-10 15:17:52 +0000251 void setObjectTypeQualifiers(Qualifiers Quals, ExprValueKind Kind) {
Fangrui Song050229d2018-11-24 00:14:31 +0000252 ObjectTypeQualifiers = Quals;
Sam McCall3dea5272019-06-10 15:17:52 +0000253 ObjectKind = Kind;
Fangrui Song050229d2018-11-24 00:14:31 +0000254 HasObjectTypeQualifiers = true;
255 }
256
257 /// Set the preferred selector.
258 ///
259 /// When an Objective-C method declaration result is added, and that
260 /// method's selector matches this preferred selector, we give that method
261 /// a slight priority boost.
262 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
263
264 /// Retrieve the code-completion context for which results are
265 /// being collected.
266 const CodeCompletionContext &getCompletionContext() const {
267 return CompletionContext;
268 }
269
270 /// Specify whether nested-name-specifiers are allowed.
271 void allowNestedNameSpecifiers(bool Allow = true) {
272 AllowNestedNameSpecifiers = Allow;
273 }
274
275 /// Return the semantic analysis object for which we are collecting
276 /// code completion results.
277 Sema &getSema() const { return SemaRef; }
278
279 /// Retrieve the allocator used to allocate code completion strings.
280 CodeCompletionAllocator &getAllocator() const { return Allocator; }
281
282 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
283
284 /// Determine whether the given declaration is at all interesting
285 /// as a code-completion result.
286 ///
287 /// \param ND the declaration that we are inspecting.
288 ///
289 /// \param AsNestedNameSpecifier will be set true if this declaration is
290 /// only interesting when it is a nested-name-specifier.
291 bool isInterestingDecl(const NamedDecl *ND,
292 bool &AsNestedNameSpecifier) const;
293
294 /// Check whether the result is hidden by the Hiding declaration.
295 ///
296 /// \returns true if the result is hidden and cannot be found, false if
297 /// the hidden result could still be found. When false, \p R may be
298 /// modified to describe how the result can be found (e.g., via extra
299 /// qualification).
300 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
301 const NamedDecl *Hiding);
302
303 /// Add a new result to this result set (if it isn't already in one
304 /// of the shadow maps), or replace an existing result (for, e.g., a
305 /// redeclaration).
306 ///
307 /// \param R the result to add (if it is unique).
308 ///
309 /// \param CurContext the context in which this result will be named.
310 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
311
312 /// Add a new result to this result set, where we already know
313 /// the hiding declaration (if any).
314 ///
315 /// \param R the result to add (if it is unique).
316 ///
317 /// \param CurContext the context in which this result will be named.
318 ///
319 /// \param Hiding the declaration that hides the result.
320 ///
321 /// \param InBaseClass whether the result was found in a base
322 /// class of the searched context.
323 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
324 bool InBaseClass);
325
326 /// Add a new non-declaration result to this result set.
327 void AddResult(Result R);
328
329 /// Enter into a new scope.
330 void EnterNewScope();
331
332 /// Exit from the current scope.
333 void ExitScope();
334
335 /// Ignore this declaration, if it is seen again.
336 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
337
338 /// Add a visited context.
339 void addVisitedContext(DeclContext *Ctx) {
340 CompletionContext.addVisitedContext(Ctx);
341 }
342
343 /// \name Name lookup predicates
344 ///
345 /// These predicates can be passed to the name lookup functions to filter the
346 /// results of name lookup. All of the predicates have the same type, so that
347 ///
348 //@{
349 bool IsOrdinaryName(const NamedDecl *ND) const;
350 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
351 bool IsIntegralConstantValue(const NamedDecl *ND) const;
352 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
353 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
354 bool IsEnum(const NamedDecl *ND) const;
355 bool IsClassOrStruct(const NamedDecl *ND) const;
356 bool IsUnion(const NamedDecl *ND) const;
357 bool IsNamespace(const NamedDecl *ND) const;
358 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
359 bool IsType(const NamedDecl *ND) const;
360 bool IsMember(const NamedDecl *ND) const;
361 bool IsObjCIvar(const NamedDecl *ND) const;
362 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
363 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
364 bool IsObjCCollection(const NamedDecl *ND) const;
365 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
366 //@}
367};
368} // namespace
Douglas Gregor3545ff42009-09-21 16:56:56 +0000369
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000370void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
371 if (isa<BlockDecl>(S.CurContext)) {
372 if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000373 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000374 Type = BSI->ReturnType;
375 ExpectedLoc = Tok;
376 }
377 } else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000378 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000379 Type = Function->getReturnType();
380 ExpectedLoc = Tok;
381 } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000382 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000383 Type = Method->getReturnType();
384 ExpectedLoc = Tok;
385 }
386}
387
388void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {
389 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000390 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000391 Type = VD ? VD->getType() : QualType();
392 ExpectedLoc = Tok;
393}
394
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000395void PreferredTypeBuilder::enterFunctionArgument(
396 SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) {
397 this->ComputeType = ComputeType;
398 Type = QualType();
399 ExpectedLoc = Tok;
400}
401
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000402void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,
403 SourceLocation LParLoc) {
404 // expected type for parenthesized expression does not change.
405 if (ExpectedLoc == LParLoc)
406 ExpectedLoc = Tok;
407}
408
409static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
410 tok::TokenKind Op) {
411 if (!LHS)
412 return QualType();
413
414 QualType LHSType = LHS->getType();
415 if (LHSType->isPointerType()) {
416 if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
417 return S.getASTContext().getPointerDiffType();
418 // Pointer difference is more common than subtracting an int from a pointer.
419 if (Op == tok::minus)
420 return LHSType;
421 }
422
423 switch (Op) {
424 // No way to infer the type of RHS from LHS.
425 case tok::comma:
426 return QualType();
427 // Prefer the type of the left operand for all of these.
428 // Arithmetic operations.
429 case tok::plus:
430 case tok::plusequal:
431 case tok::minus:
432 case tok::minusequal:
433 case tok::percent:
434 case tok::percentequal:
435 case tok::slash:
436 case tok::slashequal:
437 case tok::star:
438 case tok::starequal:
439 // Assignment.
440 case tok::equal:
441 // Comparison operators.
442 case tok::equalequal:
443 case tok::exclaimequal:
444 case tok::less:
445 case tok::lessequal:
446 case tok::greater:
447 case tok::greaterequal:
448 case tok::spaceship:
449 return LHS->getType();
450 // Binary shifts are often overloaded, so don't try to guess those.
451 case tok::greatergreater:
452 case tok::greatergreaterequal:
453 case tok::lessless:
454 case tok::lesslessequal:
455 if (LHSType->isIntegralOrEnumerationType())
456 return S.getASTContext().IntTy;
457 return QualType();
458 // Logical operators, assume we want bool.
459 case tok::ampamp:
460 case tok::pipepipe:
461 case tok::caretcaret:
462 return S.getASTContext().BoolTy;
463 // Operators often used for bit manipulation are typically used with the type
464 // of the left argument.
465 case tok::pipe:
466 case tok::pipeequal:
467 case tok::caret:
468 case tok::caretequal:
469 case tok::amp:
470 case tok::ampequal:
471 if (LHSType->isIntegralOrEnumerationType())
472 return LHSType;
473 return QualType();
474 // RHS should be a pointer to a member of the 'LHS' type, but we can't give
475 // any particular type here.
476 case tok::periodstar:
477 case tok::arrowstar:
478 return QualType();
479 default:
480 // FIXME(ibiryukov): handle the missing op, re-add the assertion.
481 // assert(false && "unhandled binary op");
482 return QualType();
483 }
484}
485
486/// Get preferred type for an argument of an unary expression. \p ContextType is
487/// preferred type of the whole unary expression.
488static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType,
489 tok::TokenKind Op) {
490 switch (Op) {
491 case tok::exclaim:
492 return S.getASTContext().BoolTy;
493 case tok::amp:
494 if (!ContextType.isNull() && ContextType->isPointerType())
495 return ContextType->getPointeeType();
496 return QualType();
497 case tok::star:
498 if (ContextType.isNull())
499 return QualType();
500 return S.getASTContext().getPointerType(ContextType.getNonReferenceType());
501 case tok::plus:
502 case tok::minus:
503 case tok::tilde:
504 case tok::minusminus:
505 case tok::plusplus:
506 if (ContextType.isNull())
507 return S.getASTContext().IntTy;
508 // leave as is, these operators typically return the same type.
509 return ContextType;
510 case tok::kw___real:
511 case tok::kw___imag:
512 return QualType();
513 default:
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000514 assert(false && "unhandled unary op");
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000515 return QualType();
516 }
517}
518
519void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,
520 tok::TokenKind Op) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000521 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000522 Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);
523 ExpectedLoc = Tok;
524}
525
526void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok,
527 Expr *Base) {
528 if (!Base)
529 return;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000530 // Do we have expected type for Base?
531 if (ExpectedLoc != Base->getBeginLoc())
532 return;
533 // Keep the expected type, only update the location.
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000534 ExpectedLoc = Tok;
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000535 return;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000536}
537
538void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,
539 tok::TokenKind OpKind,
540 SourceLocation OpLoc) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000541 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000542 Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);
543 ExpectedLoc = Tok;
544}
545
546void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,
547 Expr *LHS) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000548 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000549 Type = S.getASTContext().IntTy;
550 ExpectedLoc = Tok;
551}
552
553void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,
554 QualType CastType) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000555 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000556 Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();
557 ExpectedLoc = Tok;
558}
559
560void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000561 ComputeType = nullptr;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000562 Type = S.getASTContext().BoolTy;
563 ExpectedLoc = Tok;
564}
565
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000566class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000567 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000568 unsigned SingleDeclIndex;
569
570public:
571 typedef DeclIndexPair value_type;
572 typedef value_type reference;
573 typedef std::ptrdiff_t difference_type;
574 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000575
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000576 class pointer {
577 DeclIndexPair Value;
578
579 public:
Fangrui Song050229d2018-11-24 00:14:31 +0000580 pointer(const DeclIndexPair &Value) : Value(Value) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000581
Fangrui Song050229d2018-11-24 00:14:31 +0000582 const DeclIndexPair *operator->() const { return &Value; }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000583 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000584
585 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000586
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000587 iterator(const NamedDecl *SingleDecl, unsigned Index)
Fangrui Song050229d2018-11-24 00:14:31 +0000588 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000589
590 iterator(const DeclIndexPair *Iterator)
Fangrui Song050229d2018-11-24 00:14:31 +0000591 : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000592
593 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000594 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000595 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000596 SingleDeclIndex = 0;
597 return *this;
598 }
599
Fangrui Song050229d2018-11-24 00:14:31 +0000600 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000601 ++I;
602 DeclOrIterator = I;
603 return *this;
604 }
605
Chris Lattner9795b392010-09-04 18:12:20 +0000606 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000607 iterator tmp(*this);
608 ++(*this);
609 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000610 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000611
612 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000613 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000614 return reference(ND, SingleDeclIndex);
615
Fangrui Song050229d2018-11-24 00:14:31 +0000616 return *DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000617 }
618
Fangrui Song050229d2018-11-24 00:14:31 +0000619 pointer operator->() const { return pointer(**this); }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000620
621 friend bool operator==(const iterator &X, const iterator &Y) {
Fangrui Song050229d2018-11-24 00:14:31 +0000622 return X.DeclOrIterator.getOpaqueValue() ==
623 Y.DeclOrIterator.getOpaqueValue() &&
624 X.SingleDeclIndex == Y.SingleDeclIndex;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000625 }
626
627 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000628 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000629 }
630};
631
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000632ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000633ResultBuilder::ShadowMapEntry::begin() const {
634 if (DeclOrVector.isNull())
635 return iterator();
636
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000637 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000638 return iterator(ND, SingleDeclIndex);
639
640 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
641}
642
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000643ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000644ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000645 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000646 return iterator();
647
648 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
649}
650
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000651/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000652/// (\p CurContext) to the target context (\p TargetContext).
653///
654/// \param Context the AST context in which the qualification will be used.
655///
656/// \param CurContext the context where an entity is being named, which is
657/// typically based on the current scope.
658///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000659/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000660/// resides.
661///
662/// \returns a nested name specifier that refers into the target context, or
663/// NULL if no qualification is needed.
664static NestedNameSpecifier *
Fangrui Song050229d2018-11-24 00:14:31 +0000665getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000666 const DeclContext *TargetContext) {
667 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000668
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000669 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000670 CommonAncestor && !CommonAncestor->Encloses(CurContext);
671 CommonAncestor = CommonAncestor->getLookupParent()) {
672 if (CommonAncestor->isTransparentContext() ||
673 CommonAncestor->isFunctionOrMethod())
674 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000675
Douglas Gregor2af2f672009-09-21 20:12:40 +0000676 TargetParents.push_back(CommonAncestor);
677 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000678
679 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000680 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000681 const DeclContext *Parent = TargetParents.pop_back_val();
682
Fangrui Song050229d2018-11-24 00:14:31 +0000683 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000684 if (!Namespace->getIdentifier())
685 continue;
686
Douglas Gregor2af2f672009-09-21 20:12:40 +0000687 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Fangrui Song050229d2018-11-24 00:14:31 +0000688 } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
689 Result = NestedNameSpecifier::Create(
690 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000691 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000692 return Result;
693}
694
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000695// Some declarations have reserved names that we don't want to ever show.
696// Filter out names reserved for the implementation if they come from a
697// system header.
698static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
699 const IdentifierInfo *Id = ND->getIdentifier();
700 if (!Id)
701 return false;
702
703 // Ignore reserved names for compiler provided decls.
Vedant Kumar568db782019-11-13 18:19:32 -0800704 if (Id->isReservedName() && ND->getLocation().isInvalid())
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000705 return true;
706
707 // For system headers ignore only double-underscore names.
708 // This allows for system headers providing private symbols with a single
709 // underscore.
Vedant Kumar568db782019-11-13 18:19:32 -0800710 if (Id->isReservedName(/*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000711 SemaRef.SourceMgr.isInSystemHeader(
712 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
713 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000714
715 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000716}
717
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000718bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000719 bool &AsNestedNameSpecifier) const {
720 AsNestedNameSpecifier = false;
721
Richard Smithf2005d32015-12-29 23:34:32 +0000722 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000723 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000724
725 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000726 if (!ND->getDeclName())
727 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000728
Douglas Gregor3545ff42009-09-21 16:56:56 +0000729 // Friend declarations and declarations introduced due to friends are never
730 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000731 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000732 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000733
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000734 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000735 if (isa<ClassTemplateSpecializationDecl>(ND) ||
736 isa<ClassTemplatePartialSpecializationDecl>(ND))
737 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000738
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000739 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000740 if (isa<UsingDecl>(ND))
741 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000742
743 if (shouldIgnoreDueToReservedName(ND, SemaRef))
744 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000745
Douglas Gregor59cab552010-08-16 23:05:20 +0000746 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000747 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
748 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000749 AsNestedNameSpecifier = true;
750
Douglas Gregor3545ff42009-09-21 16:56:56 +0000751 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000752 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000753 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000754 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000755 IsNestedNameSpecifier(ND) &&
756 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000757 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000758 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
759 AsNestedNameSpecifier = true;
760 return true;
761 }
762
Douglas Gregor7c208612010-01-14 00:20:49 +0000763 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000764 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000765 // ... then it must be interesting!
766 return true;
767}
768
Douglas Gregore0717ab2010-01-14 00:41:07 +0000769bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000770 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000771 // In C, there is no way to refer to a hidden name.
772 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
773 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000774 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000775 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000776
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000777 const DeclContext *HiddenCtx =
778 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000779
Douglas Gregore0717ab2010-01-14 00:41:07 +0000780 // There is no way to qualify a name declared in a function or method.
781 if (HiddenCtx->isFunctionOrMethod())
782 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000783
Sebastian Redl50c68252010-08-31 00:36:30 +0000784 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000785 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000786
Douglas Gregore0717ab2010-01-14 00:41:07 +0000787 // We can refer to the result with the appropriate qualification. Do it.
788 R.Hidden = true;
789 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000790
Douglas Gregore0717ab2010-01-14 00:41:07 +0000791 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000792 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000793 R.Declaration->getDeclContext());
794 return false;
795}
796
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000797/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000798/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000799SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000800 switch (T->getTypeClass()) {
801 case Type::Builtin:
802 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000803 case BuiltinType::Void:
804 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000805
Fangrui Song050229d2018-11-24 00:14:31 +0000806 case BuiltinType::NullPtr:
807 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000808
Fangrui Song050229d2018-11-24 00:14:31 +0000809 case BuiltinType::Overload:
810 case BuiltinType::Dependent:
811 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000812
Fangrui Song050229d2018-11-24 00:14:31 +0000813 case BuiltinType::ObjCId:
814 case BuiltinType::ObjCClass:
815 case BuiltinType::ObjCSel:
816 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000817
Fangrui Song050229d2018-11-24 00:14:31 +0000818 default:
819 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000820 }
David Blaikie8a40f702012-01-17 06:56:22 +0000821
Douglas Gregor95887f92010-07-08 23:20:03 +0000822 case Type::Complex:
823 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000824
Douglas Gregor95887f92010-07-08 23:20:03 +0000825 case Type::Pointer:
826 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000827
Douglas Gregor95887f92010-07-08 23:20:03 +0000828 case Type::BlockPointer:
829 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000830
Douglas Gregor95887f92010-07-08 23:20:03 +0000831 case Type::LValueReference:
832 case Type::RValueReference:
833 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000834
Douglas Gregor95887f92010-07-08 23:20:03 +0000835 case Type::ConstantArray:
836 case Type::IncompleteArray:
837 case Type::VariableArray:
838 case Type::DependentSizedArray:
839 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000840
Douglas Gregor95887f92010-07-08 23:20:03 +0000841 case Type::DependentSizedExtVector:
842 case Type::Vector:
843 case Type::ExtVector:
844 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000845
Douglas Gregor95887f92010-07-08 23:20:03 +0000846 case Type::FunctionProto:
847 case Type::FunctionNoProto:
848 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000849
Douglas Gregor95887f92010-07-08 23:20:03 +0000850 case Type::Record:
851 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000852
Douglas Gregor95887f92010-07-08 23:20:03 +0000853 case Type::Enum:
854 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000855
Douglas Gregor95887f92010-07-08 23:20:03 +0000856 case Type::ObjCObject:
857 case Type::ObjCInterface:
858 case Type::ObjCObjectPointer:
859 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000860
Douglas Gregor95887f92010-07-08 23:20:03 +0000861 default:
862 return STC_Other;
863 }
864}
865
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000866/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000867/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000868QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000869 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000870
Fangrui Song050229d2018-11-24 00:14:31 +0000871 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000872 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000873 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000874 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000875
Douglas Gregor95887f92010-07-08 23:20:03 +0000876 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000877 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000878 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000879 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000880 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000881 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000882 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000883 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000884 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000885 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000886 T = Value->getType();
Ilya Biryukovc514ade2019-01-24 10:41:43 +0000887
888 if (T.isNull())
Douglas Gregor95887f92010-07-08 23:20:03 +0000889 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000890
891 // Dig through references, function pointers, and block pointers to
892 // get down to the likely type of an expression when the entity is
893 // used.
894 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000895 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000896 T = Ref->getPointeeType();
897 continue;
898 }
899
Fangrui Song050229d2018-11-24 00:14:31 +0000900 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000901 if (Pointer->getPointeeType()->isFunctionType()) {
902 T = Pointer->getPointeeType();
903 continue;
904 }
905
906 break;
907 }
908
Fangrui Song050229d2018-11-24 00:14:31 +0000909 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000910 T = Block->getPointeeType();
911 continue;
912 }
913
Fangrui Song050229d2018-11-24 00:14:31 +0000914 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000915 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000916 continue;
917 }
918
919 break;
920 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000921
Douglas Gregoraf670a82011-04-14 20:33:34 +0000922 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000923}
924
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000925unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
926 if (!ND)
927 return CCP_Unlikely;
928
929 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000930 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
931 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000932 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000933 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000934 if (ImplicitParam->getIdentifier() &&
935 ImplicitParam->getIdentifier()->isStr("_cmd"))
936 return CCP_ObjC_cmd;
937
938 return CCP_LocalDeclaration;
939 }
Richard Smith541b38b2013-09-20 01:15:31 +0000940
941 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000942 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
943 // Explicit destructor calls are very rare.
944 if (isa<CXXDestructorDecl>(ND))
945 return CCP_Unlikely;
946 // Explicit operator and conversion function calls are also very rare.
947 auto DeclNameKind = ND->getDeclName().getNameKind();
948 if (DeclNameKind == DeclarationName::CXXOperatorName ||
949 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
950 DeclNameKind == DeclarationName::CXXConversionFunctionName)
951 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000952 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000953 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000954
955 // Content-based decisions.
956 if (isa<EnumConstantDecl>(ND))
957 return CCP_Constant;
958
Douglas Gregor52e0de42013-01-31 05:03:46 +0000959 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
960 // message receiver, or parenthesized expression context. There, it's as
961 // likely that the user will want to write a type as other declarations.
962 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
963 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000964 CompletionContext.getKind() ==
965 CodeCompletionContext::CCC_ObjCMessageReceiver ||
966 CompletionContext.getKind() ==
967 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000968 return CCP_Type;
969
970 return CCP_Declaration;
971}
972
Douglas Gregor50832e02010-09-20 22:39:41 +0000973void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
974 // If this is an Objective-C method declaration whose selector matches our
975 // preferred selector, give it a priority boost.
976 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000977 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000978 if (PreferredSelector == Method->getSelector())
979 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000980
Douglas Gregor50832e02010-09-20 22:39:41 +0000981 // If we have a preferred type, adjust the priority for results with exactly-
982 // matching or nearly-matching types.
983 if (!PreferredType.isNull()) {
984 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
985 if (!T.isNull()) {
986 CanQualType TC = SemaRef.Context.getCanonicalType(T);
987 // Check for exactly-matching types (modulo qualifiers).
988 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
989 R.Priority /= CCF_ExactTypeMatch;
990 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +0000991 else if ((getSimplifiedTypeClass(PreferredType) ==
992 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000993 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000994 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000995 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000996 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000997}
998
Benjamin Kramer756ecb82019-02-11 14:52:15 +0000999static DeclContext::lookup_result getConstructors(ASTContext &Context,
1000 const CXXRecordDecl *Record) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001001 QualType RecordTy = Context.getTypeDeclType(Record);
1002 DeclarationName ConstructorName =
1003 Context.DeclarationNames.getCXXConstructorName(
1004 Context.getCanonicalType(RecordTy));
1005 return Record->lookup(ConstructorName);
1006}
1007
Douglas Gregor0212fd72010-09-21 16:06:22 +00001008void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001009 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +00001010 !CompletionContext.wantConstructorResults())
1011 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001012
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001013 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +00001014 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001015 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001016 Record = ClassTemplate->getTemplatedDecl();
1017 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
1018 // Skip specializations and partial specializations.
1019 if (isa<ClassTemplateSpecializationDecl>(Record))
1020 return;
1021 } else {
1022 // There are no constructors here.
1023 return;
1024 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001025
Douglas Gregor0212fd72010-09-21 16:06:22 +00001026 Record = Record->getDefinition();
1027 if (!Record)
1028 return;
1029
Fangrui Song050229d2018-11-24 00:14:31 +00001030 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001031 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001032 R.CursorKind = getCursorKindForDecl(R.Declaration);
1033 Results.push_back(R);
1034 }
1035}
1036
Sam McCall63c59722018-01-22 20:44:47 +00001037static bool isConstructor(const Decl *ND) {
1038 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
1039 ND = Tmpl->getTemplatedDecl();
1040 return isa<CXXConstructorDecl>(ND);
1041}
1042
Douglas Gregor7c208612010-01-14 00:20:49 +00001043void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
1044 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001045
Douglas Gregor7c208612010-01-14 00:20:49 +00001046 if (R.Kind != Result::RK_Declaration) {
1047 // For non-declaration results, just add the result.
1048 Results.push_back(R);
1049 return;
1050 }
1051
1052 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001053 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
1054 CodeCompletionResult Result(Using->getTargetDecl(),
1055 getBasePriority(Using->getTargetDecl()),
1056 R.Qualifier);
1057 Result.ShadowDecl = Using;
1058 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +00001059 return;
1060 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001061
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001062 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +00001063 unsigned IDNS = CanonDecl->getIdentifierNamespace();
1064
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001065 bool AsNestedNameSpecifier = false;
1066 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +00001067 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001068
Douglas Gregor0212fd72010-09-21 16:06:22 +00001069 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001070 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001071 return;
1072
Douglas Gregor3545ff42009-09-21 16:56:56 +00001073 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001074 ShadowMapEntry::iterator I, IEnd;
1075 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
1076 if (NamePos != SMap.end()) {
1077 I = NamePos->second.begin();
1078 IEnd = NamePos->second.end();
1079 }
1080
1081 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001082 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001083 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001084 if (ND->getCanonicalDecl() == CanonDecl) {
1085 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001086 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001087
Douglas Gregor3545ff42009-09-21 16:56:56 +00001088 // We're done.
1089 return;
1090 }
1091 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001092
Douglas Gregor3545ff42009-09-21 16:56:56 +00001093 // This is a new declaration in this scope. However, check whether this
1094 // declaration name is hidden by a similarly-named declaration in an outer
1095 // scope.
1096 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
1097 --SMEnd;
1098 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001099 ShadowMapEntry::iterator I, IEnd;
1100 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
1101 if (NamePos != SM->end()) {
1102 I = NamePos->second.begin();
1103 IEnd = NamePos->second.end();
1104 }
1105 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001106 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +00001107 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +00001108 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
1109 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001110 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001111
Douglas Gregor3545ff42009-09-21 16:56:56 +00001112 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +00001113 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
1114 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001115 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001116 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001117
Douglas Gregor3545ff42009-09-21 16:56:56 +00001118 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +00001119 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001120 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001121
Douglas Gregor3545ff42009-09-21 16:56:56 +00001122 break;
1123 }
1124 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001125
Douglas Gregor3545ff42009-09-21 16:56:56 +00001126 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001127 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001128 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00001129
Douglas Gregore412a5a2009-09-23 22:26:46 +00001130 // If the filter is for nested-name-specifiers, then this result starts a
1131 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001132 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +00001133 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001134 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001135 } else
Fangrui Song050229d2018-11-24 00:14:31 +00001136 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001137
Douglas Gregor5bf52692009-09-22 23:15:58 +00001138 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +00001139 if (R.QualifierIsInformative && !R.Qualifier &&
1140 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001141 const DeclContext *Ctx = R.Declaration->getDeclContext();
1142 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001143 R.Qualifier =
1144 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001145 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001146 R.Qualifier = NestedNameSpecifier::Create(
1147 SemaRef.Context, nullptr, false,
1148 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +00001149 else
1150 R.QualifierIsInformative = false;
1151 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001152
Douglas Gregor3545ff42009-09-21 16:56:56 +00001153 // Insert this result into the set of results and into the current shadow
1154 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001155 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001156 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001157
Douglas Gregor0212fd72010-09-21 16:06:22 +00001158 if (!AsNestedNameSpecifier)
1159 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001160}
1161
Eric Liu4a7cd632018-10-24 12:57:27 +00001162static void setInBaseClass(ResultBuilder::Result &R) {
1163 R.Priority += CCD_InBaseClass;
1164 R.InBaseClass = true;
1165}
1166
Sam McCall3dea5272019-06-10 15:17:52 +00001167enum class OverloadCompare { BothViable, Dominates, Dominated };
1168// Will Candidate ever be called on the object, when overloaded with Incumbent?
1169// Returns Dominates if Candidate is always called, Dominated if Incumbent is
1170// always called, BothViable if either may be called dependending on arguments.
1171// Precondition: must actually be overloads!
1172static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate,
1173 const CXXMethodDecl &Incumbent,
1174 const Qualifiers &ObjectQuals,
1175 ExprValueKind ObjectKind) {
Ilya Biryukov8613e902019-10-04 08:10:27 +00001176 // Base/derived shadowing is handled elsewhere.
1177 if (Candidate.getDeclContext() != Incumbent.getDeclContext())
1178 return OverloadCompare::BothViable;
Sam McCall3dea5272019-06-10 15:17:52 +00001179 if (Candidate.isVariadic() != Incumbent.isVariadic() ||
1180 Candidate.getNumParams() != Incumbent.getNumParams() ||
1181 Candidate.getMinRequiredArguments() !=
1182 Incumbent.getMinRequiredArguments())
1183 return OverloadCompare::BothViable;
1184 for (unsigned I = 0, E = Candidate.getNumParams(); I != E; ++I)
1185 if (Candidate.parameters()[I]->getType().getCanonicalType() !=
1186 Incumbent.parameters()[I]->getType().getCanonicalType())
1187 return OverloadCompare::BothViable;
1188 if (!llvm::empty(Candidate.specific_attrs<EnableIfAttr>()) ||
1189 !llvm::empty(Incumbent.specific_attrs<EnableIfAttr>()))
1190 return OverloadCompare::BothViable;
1191 // At this point, we know calls can't pick one or the other based on
1192 // arguments, so one of the two must win. (Or both fail, handled elsewhere).
1193 RefQualifierKind CandidateRef = Candidate.getRefQualifier();
1194 RefQualifierKind IncumbentRef = Incumbent.getRefQualifier();
1195 if (CandidateRef != IncumbentRef) {
1196 // If the object kind is LValue/RValue, there's one acceptable ref-qualifier
1197 // and it can't be mixed with ref-unqualified overloads (in valid code).
1198
1199 // For xvalue objects, we prefer the rvalue overload even if we have to
1200 // add qualifiers (which is rare, because const&& is rare).
1201 if (ObjectKind == clang::VK_XValue)
1202 return CandidateRef == RQ_RValue ? OverloadCompare::Dominates
1203 : OverloadCompare::Dominated;
1204 }
1205 // Now the ref qualifiers are the same (or we're in some invalid state).
1206 // So make some decision based on the qualifiers.
1207 Qualifiers CandidateQual = Candidate.getMethodQualifiers();
1208 Qualifiers IncumbentQual = Incumbent.getMethodQualifiers();
1209 bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual);
1210 bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual);
1211 if (CandidateSuperset == IncumbentSuperset)
1212 return OverloadCompare::BothViable;
1213 return IncumbentSuperset ? OverloadCompare::Dominates
1214 : OverloadCompare::Dominated;
1215}
1216
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001217void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +00001218 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001219 if (R.Kind != Result::RK_Declaration) {
1220 // For non-declaration results, just add the result.
1221 Results.push_back(R);
1222 return;
1223 }
1224
Douglas Gregorc580c522010-01-14 01:09:38 +00001225 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +00001226 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001227 CodeCompletionResult Result(Using->getTargetDecl(),
1228 getBasePriority(Using->getTargetDecl()),
1229 R.Qualifier);
1230 Result.ShadowDecl = Using;
1231 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +00001232 return;
1233 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001234
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001235 bool AsNestedNameSpecifier = false;
1236 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +00001237 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001238
Douglas Gregor0212fd72010-09-21 16:06:22 +00001239 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001240 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001241 return;
1242
Douglas Gregorc580c522010-01-14 01:09:38 +00001243 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1244 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001245
Douglas Gregorc580c522010-01-14 01:09:38 +00001246 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001247 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001248 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001249
Douglas Gregorc580c522010-01-14 01:09:38 +00001250 // If the filter is for nested-name-specifiers, then this result starts a
1251 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001252 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001253 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001254 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001255 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1256 InBaseClass &&
1257 isa<CXXRecordDecl>(
1258 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001259 R.QualifierIsInformative = true;
1260
Douglas Gregorc580c522010-01-14 01:09:38 +00001261 // If this result is supposed to have an informative qualifier, add one.
1262 if (R.QualifierIsInformative && !R.Qualifier &&
1263 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001264 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001265 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1266 R.Qualifier =
1267 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1268 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1269 R.Qualifier = NestedNameSpecifier::Create(
1270 SemaRef.Context, nullptr, false,
1271 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001272 else
1273 R.QualifierIsInformative = false;
1274 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001275
Douglas Gregora2db7932010-05-26 22:00:08 +00001276 // Adjust the priority if this result comes from a base class.
1277 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001278 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001279
Douglas Gregor50832e02010-09-20 22:39:41 +00001280 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001281
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001282 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001283 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001284 if (Method->isInstance()) {
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00001285 Qualifiers MethodQuals = Method->getMethodQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001286 if (ObjectTypeQualifiers == MethodQuals)
1287 R.Priority += CCD_ObjectQualifierMatch;
1288 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001289 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001290 // qualifiers.
1291 return;
1292 }
Sam McCall3dea5272019-06-10 15:17:52 +00001293 // Detect cases where a ref-qualified method cannot be invoked.
1294 switch (Method->getRefQualifier()) {
1295 case RQ_LValue:
1296 if (ObjectKind != VK_LValue && !MethodQuals.hasConst())
1297 return;
1298 break;
1299 case RQ_RValue:
1300 if (ObjectKind == VK_LValue)
1301 return;
1302 break;
1303 case RQ_None:
1304 break;
1305 }
1306
1307 /// Check whether this dominates another overloaded method, which should
1308 /// be suppressed (or vice versa).
1309 /// Motivating case is const_iterator begin() const vs iterator begin().
1310 auto &OverloadSet = OverloadMap[std::make_pair(
1311 CurContext, Method->getDeclName().getAsOpaqueInteger())];
Mark de Wever3ec61282019-12-17 21:54:32 +01001312 for (const DeclIndexPair Entry : OverloadSet) {
Sam McCall3dea5272019-06-10 15:17:52 +00001313 Result &Incumbent = Results[Entry.second];
1314 switch (compareOverloads(*Method,
1315 *cast<CXXMethodDecl>(Incumbent.Declaration),
1316 ObjectTypeQualifiers, ObjectKind)) {
1317 case OverloadCompare::Dominates:
1318 // Replace the dominated overload with this one.
1319 // FIXME: if the overload dominates multiple incumbents then we
1320 // should remove all. But two overloads is by far the common case.
1321 Incumbent = std::move(R);
1322 return;
1323 case OverloadCompare::Dominated:
1324 // This overload can't be called, drop it.
1325 return;
1326 case OverloadCompare::BothViable:
1327 break;
1328 }
1329 }
1330 OverloadSet.Add(Method, Results.size());
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001331 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001332
Douglas Gregorc580c522010-01-14 01:09:38 +00001333 // Insert this result into the set of results.
1334 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001335
Douglas Gregor0212fd72010-09-21 16:06:22 +00001336 if (!AsNestedNameSpecifier)
1337 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001338}
1339
Douglas Gregor78a21012010-01-14 16:01:26 +00001340void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001341 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001342 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001343 Results.push_back(R);
1344}
1345
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001346/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001347void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001348
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001349/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001350void ResultBuilder::ExitScope() {
1351 ShadowMaps.pop_back();
1352}
1353
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001354/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001355/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001356bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001357 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001358
Richard Smith541b38b2013-09-20 01:15:31 +00001359 // If name lookup finds a local extern declaration, then we are in a
1360 // context where it behaves like an ordinary name.
1361 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001362 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001363 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001364 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001365 if (isa<ObjCIvarDecl>(ND))
1366 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001367 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001368
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001369 return ND->getIdentifierNamespace() & IDNS;
1370}
1371
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001372/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001373/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001374bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001375 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001376 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001377 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001378 // Objective-C interfaces names are not filtered by this method because they
1379 // can be used in a class property expression. We can still filter out
1380 // @class declarations though.
1381 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1382 if (!ID->getDefinition())
1383 return false;
1384 }
1385
Richard Smith541b38b2013-09-20 01:15:31 +00001386 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001387 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001388 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001389 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001390 if (isa<ObjCIvarDecl>(ND))
1391 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001392 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001393
Douglas Gregor70febae2010-05-28 00:49:12 +00001394 return ND->getIdentifierNamespace() & IDNS;
1395}
1396
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001397bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001398 if (!IsOrdinaryNonTypeName(ND))
1399 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001400
Fangrui Song050229d2018-11-24 00:14:31 +00001401 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001402 if (VD->getType()->isIntegralOrEnumerationType())
1403 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001404
Douglas Gregor85b50632010-07-28 21:50:18 +00001405 return false;
1406}
1407
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001408/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001409/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001410bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001411 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001412
Richard Smith541b38b2013-09-20 01:15:31 +00001413 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001414 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001415 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001416
Fangrui Song050229d2018-11-24 00:14:31 +00001417 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1418 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001419}
1420
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001421/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001422/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001423bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001424 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001425 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001426 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001427
Douglas Gregor3545ff42009-09-21 16:56:56 +00001428 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1429}
1430
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001431/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001432bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001433 return isa<EnumDecl>(ND);
1434}
1435
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001436/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001437bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001438 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001439 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001440 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001441
1442 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001443 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1444 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1445 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001446
Douglas Gregor3545ff42009-09-21 16:56:56 +00001447 return false;
1448}
1449
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001450/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001451bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001452 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001453 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001454 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001455
Fangrui Song050229d2018-11-24 00:14:31 +00001456 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001457 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001458
Douglas Gregor3545ff42009-09-21 16:56:56 +00001459 return false;
1460}
1461
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001462/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001463bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001464 return isa<NamespaceDecl>(ND);
1465}
1466
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001467/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001468/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001469bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001470 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001471}
1472
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001473/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001474bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001475 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001476 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001477}
1478
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001479/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001480/// "." or "->". Only value declarations, nested name specifiers, and
1481/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001482bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001483 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001484 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001485 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001486}
1487
Douglas Gregora817a192010-05-27 23:06:34 +00001488static bool isObjCReceiverType(ASTContext &C, QualType T) {
1489 T = C.getCanonicalType(T);
1490 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001491 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001492 case Type::ObjCInterface:
1493 case Type::ObjCObjectPointer:
1494 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001495
Douglas Gregora817a192010-05-27 23:06:34 +00001496 case Type::Builtin:
1497 switch (cast<BuiltinType>(T)->getKind()) {
1498 case BuiltinType::ObjCId:
1499 case BuiltinType::ObjCClass:
1500 case BuiltinType::ObjCSel:
1501 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001502
Douglas Gregora817a192010-05-27 23:06:34 +00001503 default:
1504 break;
1505 }
1506 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001507
Douglas Gregora817a192010-05-27 23:06:34 +00001508 default:
1509 break;
1510 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001511
David Blaikiebbafb8a2012-03-11 07:00:24 +00001512 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001513 return false;
1514
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001515 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001516 // particular class type has any conversions to Objective-C types. For now,
1517 // just accept all class types.
1518 return T->isDependentType() || T->isRecordType();
1519}
1520
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001521bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001522 QualType T = getDeclUsageType(SemaRef.Context, ND);
1523 if (T.isNull())
1524 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001525
Douglas Gregora817a192010-05-27 23:06:34 +00001526 T = SemaRef.Context.getBaseElementType(T);
1527 return isObjCReceiverType(SemaRef.Context, T);
1528}
1529
Fangrui Song050229d2018-11-24 00:14:31 +00001530bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1531 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001532 if (IsObjCMessageReceiver(ND))
1533 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001534
Fangrui Song050229d2018-11-24 00:14:31 +00001535 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001536 if (!Var)
1537 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001538
Douglas Gregord8c61782012-02-15 15:34:24 +00001539 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1540}
1541
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001542bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001543 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1544 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001545 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001546
Douglas Gregor68762e72010-08-23 21:17:50 +00001547 QualType T = getDeclUsageType(SemaRef.Context, ND);
1548 if (T.isNull())
1549 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001550
Douglas Gregor68762e72010-08-23 21:17:50 +00001551 T = SemaRef.Context.getBaseElementType(T);
1552 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001553 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001554 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001555}
Douglas Gregora817a192010-05-27 23:06:34 +00001556
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001557bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001558 return false;
1559}
1560
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001561/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001562/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001563bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001564 return isa<ObjCIvarDecl>(ND);
1565}
1566
Douglas Gregorc580c522010-01-14 01:09:38 +00001567namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001568
Fangrui Song050229d2018-11-24 00:14:31 +00001569/// Visible declaration consumer that adds a code-completion result
1570/// for each visible declaration.
1571class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1572 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001573 DeclContext *InitialLookupCtx;
1574 // NamingClass and BaseType are used for access-checking. See
1575 // Sema::IsSimplyAccessible for details.
1576 CXXRecordDecl *NamingClass;
1577 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001578 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001579
Fangrui Song050229d2018-11-24 00:14:31 +00001580public:
1581 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001582 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1583 QualType BaseType = QualType(),
1584 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1585 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1586 FixIts(std::move(FixIts)) {
1587 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1588 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1589 if (BaseType.isNull()) {
1590 auto ThisType = Results.getSema().getCurrentThisType();
1591 if (!ThisType.isNull()) {
1592 assert(ThisType->isPointerType());
1593 BaseType = ThisType->getPointeeType();
1594 if (!NamingClass)
1595 NamingClass = BaseType->getAsCXXRecordDecl();
1596 }
1597 }
1598 this->BaseType = BaseType;
1599 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001600
Fangrui Song050229d2018-11-24 00:14:31 +00001601 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1602 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001603 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001604 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001605 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001606 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001607
Fangrui Song050229d2018-11-24 00:14:31 +00001608 void EnteredContext(DeclContext *Ctx) override {
1609 Results.addVisitedContext(Ctx);
1610 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001611
1612private:
1613 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1614 // Naming class to use for access check. In most cases it was provided
1615 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1616 // for unqualified lookup we fallback to the \p Ctx in which we found the
1617 // member.
1618 auto *NamingClass = this->NamingClass;
1619 QualType BaseType = this->BaseType;
1620 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1621 if (!NamingClass)
1622 NamingClass = Cls;
1623 // When we emulate implicit 'this->' in an unqualified lookup, we might
1624 // end up with an invalid naming class. In that case, we avoid emulating
1625 // 'this->' qualifier to satisfy preconditions of the access checking.
1626 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1627 !NamingClass->isDerivedFrom(Cls)) {
1628 NamingClass = Cls;
1629 BaseType = QualType();
1630 }
1631 } else {
1632 // The decl was found outside the C++ class, so only ObjC access checks
1633 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1634 // out.
1635 NamingClass = nullptr;
1636 BaseType = QualType();
1637 }
1638 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1639 }
Fangrui Song050229d2018-11-24 00:14:31 +00001640};
1641} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001642
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001643/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001644static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001645 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001646 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001647 Results.AddResult(Result("short", CCP_Type));
1648 Results.AddResult(Result("long", CCP_Type));
1649 Results.AddResult(Result("signed", CCP_Type));
1650 Results.AddResult(Result("unsigned", CCP_Type));
1651 Results.AddResult(Result("void", CCP_Type));
1652 Results.AddResult(Result("char", CCP_Type));
1653 Results.AddResult(Result("int", CCP_Type));
1654 Results.AddResult(Result("float", CCP_Type));
1655 Results.AddResult(Result("double", CCP_Type));
1656 Results.AddResult(Result("enum", CCP_Type));
1657 Results.AddResult(Result("struct", CCP_Type));
1658 Results.AddResult(Result("union", CCP_Type));
1659 Results.AddResult(Result("const", CCP_Type));
1660 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001661
Douglas Gregor3545ff42009-09-21 16:56:56 +00001662 if (LangOpts.C99) {
1663 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001664 Results.AddResult(Result("_Complex", CCP_Type));
1665 Results.AddResult(Result("_Imaginary", CCP_Type));
1666 Results.AddResult(Result("_Bool", CCP_Type));
1667 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001668 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001669
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001670 CodeCompletionBuilder Builder(Results.getAllocator(),
1671 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001672 if (LangOpts.CPlusPlus) {
1673 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001674 Results.AddResult(
1675 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001676 Results.AddResult(Result("class", CCP_Type));
1677 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001678
Douglas Gregorf4c33342010-05-28 00:22:41 +00001679 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001680 Builder.AddTypedTextChunk("typename");
1681 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1682 Builder.AddPlaceholderChunk("qualifier");
1683 Builder.AddTextChunk("::");
1684 Builder.AddPlaceholderChunk("name");
1685 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001686
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001687 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001688 Results.AddResult(Result("auto", CCP_Type));
1689 Results.AddResult(Result("char16_t", CCP_Type));
1690 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001691
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001692 Builder.AddTypedTextChunk("decltype");
1693 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1694 Builder.AddPlaceholderChunk("expression");
1695 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1696 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001697 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001698 } else
1699 Results.AddResult(Result("__auto_type", CCP_Type));
1700
Richard Smith7b301e22018-05-24 21:51:52 +00001701 // GNU keywords
1702 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001703 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001704 // Results.AddResult(Result("_Decimal32"));
1705 // Results.AddResult(Result("_Decimal64"));
1706 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001707
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001708 Builder.AddTypedTextChunk("typeof");
1709 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1710 Builder.AddPlaceholderChunk("expression");
1711 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001712
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001713 Builder.AddTypedTextChunk("typeof");
1714 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1715 Builder.AddPlaceholderChunk("type");
1716 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1717 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001718 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001719
1720 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001721 Results.AddResult(Result("_Nonnull", CCP_Type));
1722 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1723 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001724}
1725
John McCallfaf5fb42010-08-26 23:41:50 +00001726static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001727 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001728 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001729 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001730 // Note: we don't suggest either "auto" or "register", because both
1731 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1732 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001733 Results.AddResult(Result("extern"));
1734 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001735
1736 if (LangOpts.CPlusPlus11) {
1737 CodeCompletionAllocator &Allocator = Results.getAllocator();
1738 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1739
1740 // alignas
1741 Builder.AddTypedTextChunk("alignas");
1742 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1743 Builder.AddPlaceholderChunk("expression");
1744 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1745 Results.AddResult(Result(Builder.TakeString()));
1746
1747 Results.AddResult(Result("constexpr"));
1748 Results.AddResult(Result("thread_local"));
1749 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001750}
1751
John McCallfaf5fb42010-08-26 23:41:50 +00001752static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001753 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001754 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001755 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001756 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001757 case Sema::PCC_Class:
1758 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001759 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001760 Results.AddResult(Result("explicit"));
1761 Results.AddResult(Result("friend"));
1762 Results.AddResult(Result("mutable"));
1763 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001764 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001765 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001766
John McCallfaf5fb42010-08-26 23:41:50 +00001767 case Sema::PCC_ObjCInterface:
1768 case Sema::PCC_ObjCImplementation:
1769 case Sema::PCC_Namespace:
1770 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001771 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001772 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001773 break;
1774
John McCallfaf5fb42010-08-26 23:41:50 +00001775 case Sema::PCC_ObjCInstanceVariableList:
1776 case Sema::PCC_Expression:
1777 case Sema::PCC_Statement:
1778 case Sema::PCC_ForInit:
1779 case Sema::PCC_Condition:
1780 case Sema::PCC_RecoveryInFunction:
1781 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001782 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001783 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001784 break;
1785 }
1786}
1787
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001788static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1789static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1790static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001791 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001792static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001793 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001794static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001795 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001796static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001797
Douglas Gregorf4c33342010-05-28 00:22:41 +00001798static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001799 CodeCompletionBuilder Builder(Results.getAllocator(),
1800 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001801 Builder.AddTypedTextChunk("typedef");
1802 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1803 Builder.AddPlaceholderChunk("type");
1804 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1805 Builder.AddPlaceholderChunk("name");
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001806 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001807 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001808}
1809
John McCallfaf5fb42010-08-26 23:41:50 +00001810static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001811 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001812 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001813 case Sema::PCC_Namespace:
1814 case Sema::PCC_Class:
1815 case Sema::PCC_ObjCInstanceVariableList:
1816 case Sema::PCC_Template:
1817 case Sema::PCC_MemberTemplate:
1818 case Sema::PCC_Statement:
1819 case Sema::PCC_RecoveryInFunction:
1820 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001821 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001822 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001823 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001824
John McCallfaf5fb42010-08-26 23:41:50 +00001825 case Sema::PCC_Expression:
1826 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001827 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001828
Douglas Gregor5e35d592010-09-14 23:59:36 +00001829 case Sema::PCC_ObjCInterface:
1830 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001831 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001832
John McCallfaf5fb42010-08-26 23:41:50 +00001833 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001834 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001835 }
David Blaikie8a40f702012-01-17 06:56:22 +00001836
1837 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001838}
1839
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001840static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1841 const Preprocessor &PP) {
1842 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001843 Policy.AnonymousTagLocations = false;
1844 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001845 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001846 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001847 return Policy;
1848}
1849
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001850/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001851static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1852 return getCompletionPrintingPolicy(S.Context, S.PP);
1853}
1854
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001855/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001856/// that has the appropriate lifetime for code completion.
1857///
1858/// This routine provides a fast path where we provide constant strings for
1859/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001860static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001861 const PrintingPolicy &Policy,
1862 CodeCompletionAllocator &Allocator) {
1863 if (!T.getLocalQualifiers()) {
1864 // Built-in type names are constant strings.
1865 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001866 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001867
Douglas Gregore5c79d52011-10-18 21:20:17 +00001868 // Anonymous tag types are constant strings.
1869 if (const TagType *TagT = dyn_cast<TagType>(T))
1870 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001871 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001872 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001873 case TTK_Struct:
1874 return "struct <anonymous>";
1875 case TTK_Interface:
1876 return "__interface <anonymous>";
1877 case TTK_Class:
1878 return "class <anonymous>";
1879 case TTK_Union:
1880 return "union <anonymous>";
1881 case TTK_Enum:
1882 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001883 }
1884 }
1885 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001886
Douglas Gregore5c79d52011-10-18 21:20:17 +00001887 // Slow path: format the type as a string.
1888 std::string Result;
1889 T.getAsStringInternal(Result, Policy);
1890 return Allocator.CopyString(Result);
1891}
1892
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001893/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001894static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1895 QualType ThisTy = S.getCurrentThisType();
1896 if (ThisTy.isNull())
1897 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001898
Douglas Gregord8c61782012-02-15 15:34:24 +00001899 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001900 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001901 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001902 Builder.AddResultTypeChunk(
1903 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001904 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001905 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001906}
1907
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001908static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1909 ResultBuilder &Results,
1910 const LangOptions &LangOpts) {
1911 if (!LangOpts.CPlusPlus11)
1912 return;
1913
1914 Builder.AddTypedTextChunk("static_assert");
1915 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1916 Builder.AddPlaceholderChunk("expression");
1917 Builder.AddChunk(CodeCompletionString::CK_Comma);
1918 Builder.AddPlaceholderChunk("message");
1919 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001920 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001921 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1922}
1923
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001924static void AddOverrideResults(ResultBuilder &Results,
1925 const CodeCompletionContext &CCContext,
1926 CodeCompletionBuilder &Builder) {
1927 Sema &S = Results.getSema();
1928 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1929 // If not inside a class/struct/union return empty.
1930 if (!CR)
1931 return;
1932 // First store overrides within current class.
1933 // These are stored by name to make querying fast in the later step.
1934 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1935 for (auto *Method : CR->methods()) {
1936 if (!Method->isVirtual() || !Method->getIdentifier())
1937 continue;
1938 Overrides[Method->getName()].push_back(Method);
1939 }
1940
1941 for (const auto &Base : CR->bases()) {
1942 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1943 if (!BR)
1944 continue;
1945 for (auto *Method : BR->methods()) {
1946 if (!Method->isVirtual() || !Method->getIdentifier())
1947 continue;
1948 const auto it = Overrides.find(Method->getName());
1949 bool IsOverriden = false;
1950 if (it != Overrides.end()) {
1951 for (auto *MD : it->second) {
1952 // If the method in current body is not an overload of this virtual
1953 // function, then it overrides this one.
1954 if (!S.IsOverload(MD, Method, false)) {
1955 IsOverriden = true;
1956 break;
1957 }
1958 }
1959 }
1960 if (!IsOverriden) {
1961 // Generates a new CodeCompletionResult by taking this function and
1962 // converting it into an override declaration with only one chunk in the
1963 // final CodeCompletionString as a TypedTextChunk.
1964 std::string OverrideSignature;
1965 llvm::raw_string_ostream OS(OverrideSignature);
1966 CodeCompletionResult CCR(Method, 0);
1967 PrintingPolicy Policy =
1968 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1969 auto *CCS = CCR.createCodeCompletionStringForOverride(
1970 S.getPreprocessor(), S.getASTContext(), Builder,
1971 /*IncludeBriefComments=*/false, CCContext, Policy);
1972 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1973 }
1974 }
1975 }
1976}
1977
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001978/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001979static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1980 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001981 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001982 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001983
John McCall276321a2010-08-25 06:19:51 +00001984 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001985 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001986 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001987 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001988 if (Results.includeCodePatterns()) {
1989 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001990 Builder.AddTypedTextChunk("namespace");
1991 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1992 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00001993 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001994 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00001995 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001996 Builder.AddPlaceholderChunk("declarations");
1997 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1998 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1999 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002000 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002001
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002002 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002003 Builder.AddTypedTextChunk("namespace");
2004 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2005 Builder.AddPlaceholderChunk("name");
2006 Builder.AddChunk(CodeCompletionString::CK_Equal);
2007 Builder.AddPlaceholderChunk("namespace");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002008 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002009 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002010
2011 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002012 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002013 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2014 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002015 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002016 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002017
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002018 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002019 Builder.AddTypedTextChunk("asm");
2020 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2021 Builder.AddPlaceholderChunk("string-literal");
2022 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2023 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002024
Douglas Gregorf4c33342010-05-28 00:22:41 +00002025 if (Results.includeCodePatterns()) {
2026 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002027 Builder.AddTypedTextChunk("template");
2028 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2029 Builder.AddPlaceholderChunk("declaration");
2030 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002031 } else {
2032 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002033 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002034 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002035
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002036 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002037 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002038
Douglas Gregorf4c33342010-05-28 00:22:41 +00002039 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002040 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002041
John McCallfaf5fb42010-08-26 23:41:50 +00002042 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002043 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002044 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002045 Builder.AddTypedTextChunk("using");
2046 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2047 Builder.AddPlaceholderChunk("qualifier");
2048 Builder.AddTextChunk("::");
2049 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002050 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002051 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002052
Douglas Gregorf4c33342010-05-28 00:22:41 +00002053 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002054 if (SemaRef.CurContext->isDependentContext()) {
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002055 Builder.AddTypedTextChunk("using typename");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002056 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2057 Builder.AddPlaceholderChunk("qualifier");
2058 Builder.AddTextChunk("::");
2059 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002060 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002061 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002062 }
2063
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002064 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
2065
John McCallfaf5fb42010-08-26 23:41:50 +00002066 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002067 AddTypedefResult(Results);
2068
Erik Verbruggen6524c052017-10-24 13:46:58 +00002069 bool IsNotInheritanceScope =
2070 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002071 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002072 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002073 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002074 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002075 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002076
2077 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002078 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002079 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002080 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002081 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002082
2083 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002084 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002085 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002086 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002087 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002088
2089 // FIXME: This adds override results only if we are at the first word of
2090 // the declaration/definition. Also call this from other sides to have
2091 // more use-cases.
2092 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
2093 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002094 }
2095 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002096 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002097
John McCallfaf5fb42010-08-26 23:41:50 +00002098 case Sema::PCC_Template:
2099 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002100 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002101 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002102 Builder.AddTypedTextChunk("template");
2103 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2104 Builder.AddPlaceholderChunk("parameters");
2105 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2106 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002107 } else {
2108 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002109 }
2110
David Blaikiebbafb8a2012-03-11 07:00:24 +00002111 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2112 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002113 break;
2114
John McCallfaf5fb42010-08-26 23:41:50 +00002115 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002116 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2117 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2118 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002119 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002120
John McCallfaf5fb42010-08-26 23:41:50 +00002121 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002122 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2123 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2124 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002125 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002126
John McCallfaf5fb42010-08-26 23:41:50 +00002127 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002128 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002129 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002130
John McCallfaf5fb42010-08-26 23:41:50 +00002131 case Sema::PCC_RecoveryInFunction:
2132 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002133 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002134
David Blaikiebbafb8a2012-03-11 07:00:24 +00002135 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2136 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002137 Builder.AddTypedTextChunk("try");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002138 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002139 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002140 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002141 Builder.AddPlaceholderChunk("statements");
2142 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2143 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002144 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002145 Builder.AddTextChunk("catch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002146 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002147 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2148 Builder.AddPlaceholderChunk("declaration");
2149 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002150 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002151 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002152 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002153 Builder.AddPlaceholderChunk("statements");
2154 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2155 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2156 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002157 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002158 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002159 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002160
Douglas Gregorf64acca2010-05-25 21:41:55 +00002161 if (Results.includeCodePatterns()) {
2162 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002163 Builder.AddTypedTextChunk("if");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002164 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002165 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002166 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002167 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002168 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002169 Builder.AddPlaceholderChunk("expression");
2170 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002171 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002172 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002173 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002174 Builder.AddPlaceholderChunk("statements");
2175 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2176 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2177 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002178
Douglas Gregorf64acca2010-05-25 21:41:55 +00002179 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002180 Builder.AddTypedTextChunk("switch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002181 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002182 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002183 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002184 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002185 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002186 Builder.AddPlaceholderChunk("expression");
2187 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002188 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002189 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2190 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002191 Builder.AddPlaceholderChunk("cases");
2192 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002193 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2194 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002195 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002196
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002197 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002198 if (SemaRef.getCurFunction() &&
2199 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002200 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002201 Builder.AddTypedTextChunk("case");
2202 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2203 Builder.AddPlaceholderChunk("expression");
2204 Builder.AddChunk(CodeCompletionString::CK_Colon);
2205 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002206
2207 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002208 Builder.AddTypedTextChunk("default");
2209 Builder.AddChunk(CodeCompletionString::CK_Colon);
2210 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002211 }
2212
Douglas Gregorf64acca2010-05-25 21:41:55 +00002213 if (Results.includeCodePatterns()) {
2214 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002215 Builder.AddTypedTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002216 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002217 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002218 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002219 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002220 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002221 Builder.AddPlaceholderChunk("expression");
2222 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002223 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002224 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002225 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002226 Builder.AddPlaceholderChunk("statements");
2227 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2228 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2229 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002230
2231 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002232 Builder.AddTypedTextChunk("do");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002233 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002234 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002235 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002236 Builder.AddPlaceholderChunk("statements");
2237 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2238 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2239 Builder.AddTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002240 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002241 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2242 Builder.AddPlaceholderChunk("expression");
2243 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2244 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002245
Douglas Gregorf64acca2010-05-25 21:41:55 +00002246 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002247 Builder.AddTypedTextChunk("for");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002248 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002249 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002250 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002251 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002252 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002253 Builder.AddPlaceholderChunk("init-expression");
2254 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002255 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002256 Builder.AddPlaceholderChunk("condition");
2257 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002258 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002259 Builder.AddPlaceholderChunk("inc-expression");
2260 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002261 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002262 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2263 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2264 Builder.AddPlaceholderChunk("statements");
2265 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2266 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2267 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002268 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002269
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002270 if (S->getContinueParent()) {
2271 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002272 Builder.AddTypedTextChunk("continue");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002273 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002274 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002275 }
2276
2277 if (S->getBreakParent()) {
2278 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002279 Builder.AddTypedTextChunk("break");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002280 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002281 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002282 }
2283
Ilya Biryukov32497f52019-05-27 09:52:09 +00002284 // "return expression ;" or "return ;", depending on the return type.
2285 QualType ReturnType;
Fangrui Song050229d2018-11-24 00:14:31 +00002286 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002287 ReturnType = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002288 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002289 ReturnType = Method->getReturnType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002290 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002291 !SemaRef.getCurBlock()->ReturnType.isNull())
Ilya Biryukov32497f52019-05-27 09:52:09 +00002292 ReturnType = SemaRef.getCurBlock()->ReturnType;;
2293 if (ReturnType.isNull() || ReturnType->isVoidType()) {
2294 Builder.AddTypedTextChunk("return");
2295 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2296 Results.AddResult(Result(Builder.TakeString()));
2297 } else {
2298 assert(!ReturnType.isNull());
2299 // "return expression ;"
2300 Builder.AddTypedTextChunk("return");
2301 Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002302 Builder.AddPlaceholderChunk("expression");
Ilya Biryukov32497f52019-05-27 09:52:09 +00002303 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2304 Results.AddResult(Result(Builder.TakeString()));
2305 // When boolean, also add 'return true;' and 'return false;'.
2306 if (ReturnType->isBooleanType()) {
2307 Builder.AddTypedTextChunk("return true");
2308 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2309 Results.AddResult(Result(Builder.TakeString()));
2310
2311 Builder.AddTypedTextChunk("return false");
2312 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2313 Results.AddResult(Result(Builder.TakeString()));
2314 }
Ilya Biryukov57a51b62020-01-10 11:50:27 +01002315 // For pointers, suggest 'return nullptr' in C++.
2316 if (SemaRef.getLangOpts().CPlusPlus11 &&
2317 (ReturnType->isPointerType() || ReturnType->isMemberPointerType())) {
2318 Builder.AddTypedTextChunk("return nullptr");
2319 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2320 Results.AddResult(Result(Builder.TakeString()));
2321 }
Douglas Gregor44272ca2010-02-18 04:06:48 +00002322 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002323
Douglas Gregorf4c33342010-05-28 00:22:41 +00002324 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002325 Builder.AddTypedTextChunk("goto");
2326 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2327 Builder.AddPlaceholderChunk("label");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002328 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002329 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002330
Douglas Gregorf4c33342010-05-28 00:22:41 +00002331 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002332 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002333 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2334 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002335 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002336 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002337
2338 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002339 }
Fangrui Song050229d2018-11-24 00:14:31 +00002340 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002341
2342 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002343 case Sema::PCC_ForInit:
2344 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002345 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002346 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002347 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002348
Douglas Gregor5e35d592010-09-14 23:59:36 +00002349 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002350 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002351 CCC == Sema::PCC_ParenthesizedExpression) {
2352 // (__bridge <type>)<expression>
2353 Builder.AddTypedTextChunk("__bridge");
2354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2355 Builder.AddPlaceholderChunk("type");
2356 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2357 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002358 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002359
2360 // (__bridge_transfer <Objective-C type>)<expression>
2361 Builder.AddTypedTextChunk("__bridge_transfer");
2362 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2363 Builder.AddPlaceholderChunk("Objective-C type");
2364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2365 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002366 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002367
2368 // (__bridge_retained <CF type>)<expression>
2369 Builder.AddTypedTextChunk("__bridge_retained");
2370 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2371 Builder.AddPlaceholderChunk("CF type");
2372 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2373 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002374 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002375 }
2376 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002377 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002378
John McCallfaf5fb42010-08-26 23:41:50 +00002379 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002380 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002381 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002382 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002383
Douglas Gregore5c79d52011-10-18 21:20:17 +00002384 // true
2385 Builder.AddResultTypeChunk("bool");
2386 Builder.AddTypedTextChunk("true");
2387 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002388
Douglas Gregore5c79d52011-10-18 21:20:17 +00002389 // false
2390 Builder.AddResultTypeChunk("bool");
2391 Builder.AddTypedTextChunk("false");
2392 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002393
David Blaikiebbafb8a2012-03-11 07:00:24 +00002394 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002395 // dynamic_cast < type-id > ( expression )
2396 Builder.AddTypedTextChunk("dynamic_cast");
2397 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2398 Builder.AddPlaceholderChunk("type");
2399 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2400 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2401 Builder.AddPlaceholderChunk("expression");
2402 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002403 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002404 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002405
Douglas Gregorf4c33342010-05-28 00:22:41 +00002406 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002407 Builder.AddTypedTextChunk("static_cast");
2408 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2409 Builder.AddPlaceholderChunk("type");
2410 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2411 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2412 Builder.AddPlaceholderChunk("expression");
2413 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002414 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002415
Douglas Gregorf4c33342010-05-28 00:22:41 +00002416 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002417 Builder.AddTypedTextChunk("reinterpret_cast");
2418 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2419 Builder.AddPlaceholderChunk("type");
2420 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2421 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2422 Builder.AddPlaceholderChunk("expression");
2423 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002424 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002425
Douglas Gregorf4c33342010-05-28 00:22:41 +00002426 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002427 Builder.AddTypedTextChunk("const_cast");
2428 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2429 Builder.AddPlaceholderChunk("type");
2430 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2431 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2432 Builder.AddPlaceholderChunk("expression");
2433 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002434 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002435
David Blaikiebbafb8a2012-03-11 07:00:24 +00002436 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002437 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002438 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002439 Builder.AddTypedTextChunk("typeid");
2440 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2441 Builder.AddPlaceholderChunk("expression-or-type");
2442 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002443 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002444 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002445
Douglas Gregorf4c33342010-05-28 00:22:41 +00002446 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002447 Builder.AddTypedTextChunk("new");
2448 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2449 Builder.AddPlaceholderChunk("type");
2450 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2451 Builder.AddPlaceholderChunk("expressions");
2452 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002453 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002454
Douglas Gregorf4c33342010-05-28 00:22:41 +00002455 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002456 Builder.AddTypedTextChunk("new");
2457 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2458 Builder.AddPlaceholderChunk("type");
2459 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2460 Builder.AddPlaceholderChunk("size");
2461 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2462 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2463 Builder.AddPlaceholderChunk("expressions");
2464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002465 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002466
Douglas Gregorf4c33342010-05-28 00:22:41 +00002467 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002468 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002469 Builder.AddTypedTextChunk("delete");
2470 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2471 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002472 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002473
Douglas Gregorf4c33342010-05-28 00:22:41 +00002474 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002475 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002476 Builder.AddTypedTextChunk("delete");
2477 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2478 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2479 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2480 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2481 Builder.AddPlaceholderChunk("expression");
2482 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002483
David Blaikiebbafb8a2012-03-11 07:00:24 +00002484 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002485 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002486 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002487 Builder.AddTypedTextChunk("throw");
2488 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2489 Builder.AddPlaceholderChunk("expression");
2490 Results.AddResult(Result(Builder.TakeString()));
2491 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002492
Douglas Gregora2db7932010-05-26 22:00:08 +00002493 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002494
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002495 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002496 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002497 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002498 Builder.AddTypedTextChunk("nullptr");
2499 Results.AddResult(Result(Builder.TakeString()));
2500
2501 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002502 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002503 Builder.AddTypedTextChunk("alignof");
2504 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2505 Builder.AddPlaceholderChunk("type");
2506 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2507 Results.AddResult(Result(Builder.TakeString()));
2508
2509 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002510 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002511 Builder.AddTypedTextChunk("noexcept");
2512 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2513 Builder.AddPlaceholderChunk("expression");
2514 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2515 Results.AddResult(Result(Builder.TakeString()));
2516
2517 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002518 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002519 Builder.AddTypedTextChunk("sizeof...");
2520 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2521 Builder.AddPlaceholderChunk("parameter-pack");
2522 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2523 Results.AddResult(Result(Builder.TakeString()));
2524 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002525 }
2526
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002527 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002528 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002529 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2530 // The interface can be NULL.
2531 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002532 if (ID->getSuperClass()) {
2533 std::string SuperType;
2534 SuperType = ID->getSuperClass()->getNameAsString();
2535 if (Method->isInstanceMethod())
2536 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002537
Douglas Gregore5c79d52011-10-18 21:20:17 +00002538 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2539 Builder.AddTypedTextChunk("super");
2540 Results.AddResult(Result(Builder.TakeString()));
2541 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002542 }
2543
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002544 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002545 }
2546
Jordan Rose58d54722012-06-30 21:33:57 +00002547 if (SemaRef.getLangOpts().C11) {
2548 // _Alignof
2549 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002550 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002551 Builder.AddTypedTextChunk("alignof");
2552 else
2553 Builder.AddTypedTextChunk("_Alignof");
2554 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2555 Builder.AddPlaceholderChunk("type");
2556 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2557 Results.AddResult(Result(Builder.TakeString()));
2558 }
2559
Douglas Gregorf4c33342010-05-28 00:22:41 +00002560 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002561 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002562 Builder.AddTypedTextChunk("sizeof");
2563 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2564 Builder.AddPlaceholderChunk("expression-or-type");
2565 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2566 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002567 break;
2568 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002569
John McCallfaf5fb42010-08-26 23:41:50 +00002570 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002571 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002572 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002573 }
2574
David Blaikiebbafb8a2012-03-11 07:00:24 +00002575 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2576 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002577
David Blaikiebbafb8a2012-03-11 07:00:24 +00002578 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002579 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002580}
2581
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002582/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002583/// type chunk.
2584static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002585 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002586 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002587 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002588 if (!ND)
2589 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002590
2591 // Skip constructors and conversion functions, which have their return types
2592 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002593 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002594 return;
2595
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002596 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002597 QualType T;
2598 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002599 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002600 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002601 if (!BaseType.isNull())
2602 T = Method->getSendResultType(BaseType);
2603 else
2604 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002605 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002606 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002607 T = clang::TypeName::getFullyQualifiedType(T, Context);
2608 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002609 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002610 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002611 if (!BaseType.isNull())
2612 T = Ivar->getUsageType(BaseType);
2613 else
2614 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002615 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002616 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002617 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002618 if (!BaseType.isNull())
2619 T = Property->getUsageType(BaseType);
2620 else
2621 T = Property->getType();
2622 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002623
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002624 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2625 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002626
Fangrui Song050229d2018-11-24 00:14:31 +00002627 Result.AddResultTypeChunk(
2628 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002629}
2630
Richard Smith20e883e2015-04-29 23:20:19 +00002631static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002632 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002633 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002634 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2635 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002636 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002637 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002638 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002639 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002640 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002641 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002642 }
2643}
2644
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002645static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002646 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002647 std::string Result;
2648 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002649 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002650 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002651 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002652 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002653 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002654 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002655 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002656 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002657 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002658 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002659 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002660 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2661 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2662 switch (*nullability) {
2663 case NullabilityKind::NonNull:
2664 Result += "nonnull ";
2665 break;
2666
2667 case NullabilityKind::Nullable:
2668 Result += "nullable ";
2669 break;
2670
2671 case NullabilityKind::Unspecified:
2672 Result += "null_unspecified ";
2673 break;
2674 }
2675 }
2676 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002677 return Result;
2678}
2679
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002680/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002681/// block placeholder.
2682///
2683/// This function ignores things like typedefs and qualifiers in order to
2684/// present the most relevant and accurate block placeholders in code completion
2685/// results.
2686static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2687 FunctionTypeLoc &Block,
2688 FunctionProtoTypeLoc &BlockProto,
2689 bool SuppressBlock = false) {
2690 if (!TSInfo)
2691 return;
2692 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2693 while (true) {
2694 // Look through typedefs.
2695 if (!SuppressBlock) {
2696 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2697 if (TypeSourceInfo *InnerTSInfo =
2698 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2699 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2700 continue;
2701 }
2702 }
2703
2704 // Look through qualified types
2705 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2706 TL = QualifiedTL.getUnqualifiedLoc();
2707 continue;
2708 }
2709
2710 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2711 TL = AttrTL.getModifiedLoc();
2712 continue;
2713 }
2714 }
2715
2716 // Try to get the function prototype behind the block pointer type,
2717 // then we're done.
2718 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2719 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2720 Block = TL.getAs<FunctionTypeLoc>();
2721 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2722 }
2723 break;
2724 }
2725}
2726
Alex Lorenz920ae142016-10-18 10:38:58 +00002727static std::string
2728formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2729 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002730 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002731 bool SuppressBlock = false,
2732 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2733
Fangrui Song050229d2018-11-24 00:14:31 +00002734static std::string
2735FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2736 bool SuppressName = false, bool SuppressBlock = false,
2737 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Sam McCallbc7ff892019-04-04 11:34:18 +00002738 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.
2739 // It would be better to pass in the param Type, which is usually avaliable.
2740 // But this case is rare, so just pretend we fell back to int as elsewhere.
2741 if (!Param)
2742 return "int";
Douglas Gregore90dd002010-08-24 16:15:59 +00002743 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2744 if (Param->getType()->isDependentType() ||
2745 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002746 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002747 // containing that parameter's type.
2748 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002749
Douglas Gregor981a0c42010-08-29 19:47:46 +00002750 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002751 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002752
Douglas Gregor86b42682015-06-19 18:27:52 +00002753 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002754 if (ObjCSubsts)
2755 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2756 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002757 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002758 Result =
2759 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002760 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002761 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002762 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002763 } else {
2764 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002765 }
2766 return Result;
2767 }
Alex Lorenza1951202016-10-18 10:35:27 +00002768
Douglas Gregore90dd002010-08-24 16:15:59 +00002769 // The argument for a block pointer parameter is a block literal with
2770 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002771 FunctionTypeLoc Block;
2772 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002773 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2774 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002775 // Try to retrieve the block type information from the property if this is a
2776 // parameter in a setter.
2777 if (!Block && ObjCMethodParam &&
2778 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2779 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2780 ->findPropertyDecl(/*CheckOverrides=*/false))
2781 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2782 SuppressBlock);
2783 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002784
2785 if (!Block) {
2786 // We were unable to find a FunctionProtoTypeLoc with parameter names
2787 // for the block; just use the parameter type as a placeholder.
2788 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002789 if (!ObjCMethodParam && Param->getIdentifier())
2790 Result = Param->getIdentifier()->getName();
2791
Douglas Gregor86b42682015-06-19 18:27:52 +00002792 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002793
Douglas Gregore90dd002010-08-24 16:15:59 +00002794 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002795 Result = Type.getAsString(Policy);
2796 std::string Quals =
2797 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2798 if (!Quals.empty())
2799 Result = "(" + Quals + " " + Result + ")";
2800 if (Result.back() != ')')
2801 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002802 if (Param->getIdentifier())
2803 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002804 } else {
2805 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002806 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002807
Douglas Gregore90dd002010-08-24 16:15:59 +00002808 return Result;
2809 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002810
Douglas Gregore90dd002010-08-24 16:15:59 +00002811 // We have the function prototype behind the block pointer type, as it was
2812 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002813 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2814 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002815 ObjCSubsts);
2816}
2817
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002818/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002819/// declaration.
2820///
2821/// \param BlockDecl A declaration with an Objective-C block type.
2822///
2823/// \param Block The most relevant type location for that block type.
2824///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002825/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002826/// declaration is included in the resulting string.
2827static std::string
2828formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2829 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002830 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002831 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002832 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002833 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002834 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002835 ResultType =
2836 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2837 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002838 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002839 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002840
2841 // Format the parameter list.
2842 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002843 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002844 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002845 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002846 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002847 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002848 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002849 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002850 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002851 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002852 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002853 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002854 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002855 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002856
David Blaikie6adc78e2013-02-18 22:06:02 +00002857 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002858 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002859 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002860 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002861 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002862
Douglas Gregord793e7c2011-10-18 04:23:19 +00002863 if (SuppressBlock) {
2864 // Format as a parameter.
2865 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002866 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002867 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002868 Result += ")";
2869 Result += Params;
2870 } else {
2871 // Format as a block literal argument.
2872 Result = '^' + Result;
2873 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002874
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002875 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002876 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002877 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002878
Douglas Gregore90dd002010-08-24 16:15:59 +00002879 return Result;
2880}
2881
Erik Verbruggen11338c52017-07-19 10:45:40 +00002882static std::string GetDefaultValueString(const ParmVarDecl *Param,
2883 const SourceManager &SM,
2884 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002885 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002886 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2887 bool Invalid = CharSrcRange.isInvalid();
2888 if (Invalid)
2889 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002890 StringRef srcText =
2891 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002892 if (Invalid)
2893 return "";
2894
2895 if (srcText.empty() || srcText == "=") {
2896 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002897 // This happens if the code is incorrect (for example class is forward
2898 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002899 return "";
2900 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002901 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002902 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2903 // this value always has (or always does not have) '=' in front of it
2904 if (DefValue.at(0) != '=') {
2905 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002906 // Lexer returns built-in types values without '=' and user-defined types
2907 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002908 return " = " + DefValue;
2909 }
2910 return " " + DefValue;
2911}
2912
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002913/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002914static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002915 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002916 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002917 CodeCompletionBuilder &Result,
2918 unsigned Start = 0,
2919 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002920 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002921
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002922 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002923 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002924
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002925 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002926 // When we see an optional default argument, put that argument and
2927 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002928 CodeCompletionBuilder Opt(Result.getAllocator(),
2929 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002930 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002931 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002932 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002933 Result.AddOptionalChunk(Opt.TakeString());
2934 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002935 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002936
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002937 if (FirstParameter)
2938 FirstParameter = false;
2939 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002940 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002941
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002942 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002943
Douglas Gregor3545ff42009-09-21 16:56:56 +00002944 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002945 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002946 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002947 PlaceholderStr +=
2948 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002949
Douglas Gregor400f5972010-08-31 05:13:43 +00002950 if (Function->isVariadic() && P == N - 1)
2951 PlaceholderStr += ", ...";
2952
Douglas Gregor3545ff42009-09-21 16:56:56 +00002953 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002954 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002955 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002956 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002957
Fangrui Song050229d2018-11-24 00:14:31 +00002958 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002959 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002960 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002961 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002962
Richard Smith20e883e2015-04-29 23:20:19 +00002963 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002964 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002965}
2966
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002967/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002968static void AddTemplateParameterChunks(
2969 ASTContext &Context, const PrintingPolicy &Policy,
2970 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2971 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002972 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002973
2974 // Prefer to take the template parameter names from the first declaration of
2975 // the template.
2976 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2977
Douglas Gregor3545ff42009-09-21 16:56:56 +00002978 TemplateParameterList *Params = Template->getTemplateParameters();
2979 TemplateParameterList::iterator PEnd = Params->end();
2980 if (MaxParameters)
2981 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002982 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2983 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002984 bool HasDefaultArg = false;
2985 std::string PlaceholderStr;
2986 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2987 if (TTP->wasDeclaredWithTypename())
2988 PlaceholderStr = "typename";
2989 else
2990 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002991
Douglas Gregor3545ff42009-09-21 16:56:56 +00002992 if (TTP->getIdentifier()) {
2993 PlaceholderStr += ' ';
2994 PlaceholderStr += TTP->getIdentifier()->getName();
2995 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002996
Douglas Gregor3545ff42009-09-21 16:56:56 +00002997 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002998 } else if (NonTypeTemplateParmDecl *NTTP =
2999 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003000 if (NTTP->getIdentifier())
3001 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00003002 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003003 HasDefaultArg = NTTP->hasDefaultArgument();
3004 } else {
3005 assert(isa<TemplateTemplateParmDecl>(*P));
3006 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003007
Douglas Gregor3545ff42009-09-21 16:56:56 +00003008 // Since putting the template argument list into the placeholder would
3009 // be very, very long, we just use an abbreviation.
3010 PlaceholderStr = "template<...> class";
3011 if (TTP->getIdentifier()) {
3012 PlaceholderStr += ' ';
3013 PlaceholderStr += TTP->getIdentifier()->getName();
3014 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003015
Douglas Gregor3545ff42009-09-21 16:56:56 +00003016 HasDefaultArg = TTP->hasDefaultArgument();
3017 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003018
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003019 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003020 // When we see an optional default argument, put that argument and
3021 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003022 CodeCompletionBuilder Opt(Result.getAllocator(),
3023 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003024 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003025 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00003026 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003027 P - Params->begin(), true);
3028 Result.AddOptionalChunk(Opt.TakeString());
3029 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003030 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003031
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003032 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003033
Douglas Gregor3545ff42009-09-21 16:56:56 +00003034 if (FirstParameter)
3035 FirstParameter = false;
3036 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003037 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003038
Douglas Gregor3545ff42009-09-21 16:56:56 +00003039 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003040 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003041 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003042 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003043}
3044
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003045/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00003046/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00003047static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
3048 NestedNameSpecifier *Qualifier,
3049 bool QualifierIsInformative,
3050 ASTContext &Context,
3051 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003052 if (!Qualifier)
3053 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003054
Douglas Gregorf2510672009-09-21 19:57:38 +00003055 std::string PrintedNNS;
3056 {
3057 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00003058 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00003059 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00003060 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003061 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00003062 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003063 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00003064}
3065
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003066static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003067AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003068 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00003069 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003070 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00003071 return;
3072
Douglas Gregor304f9b02011-02-01 21:15:40 +00003073 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003074
Douglas Gregor304f9b02011-02-01 21:15:40 +00003075 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003076 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003077 Result.AddInformativeChunk(" const");
3078 return;
3079 }
3080
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003081 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003082 Result.AddInformativeChunk(" volatile");
3083 return;
3084 }
3085
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003086 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003087 Result.AddInformativeChunk(" restrict");
3088 return;
3089 }
3090
3091 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00003092 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00003093 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00003094 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00003095 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00003096 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00003097 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00003098 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003099 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00003100}
3101
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003102/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00003103static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003104 const NamedDecl *ND,
3105 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00003106 DeclarationName Name = ND->getDeclName();
3107 if (!Name)
3108 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003109
Douglas Gregor0212fd72010-09-21 16:06:22 +00003110 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003111 case DeclarationName::CXXOperatorName: {
3112 const char *OperatorName = nullptr;
3113 switch (Name.getCXXOverloadedOperator()) {
3114 case OO_None:
3115 case OO_Conditional:
3116 case NUM_OVERLOADED_OPERATORS:
3117 OperatorName = "operator";
3118 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003119
Fangrui Song050229d2018-11-24 00:14:31 +00003120#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
3121 case OO_##Name: \
3122 OperatorName = "operator" Spelling; \
3123 break;
3124#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00003125#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003126
Fangrui Song050229d2018-11-24 00:14:31 +00003127 case OO_New:
3128 OperatorName = "operator new";
3129 break;
3130 case OO_Delete:
3131 OperatorName = "operator delete";
3132 break;
3133 case OO_Array_New:
3134 OperatorName = "operator new[]";
3135 break;
3136 case OO_Array_Delete:
3137 OperatorName = "operator delete[]";
3138 break;
3139 case OO_Call:
3140 OperatorName = "operator()";
3141 break;
3142 case OO_Subscript:
3143 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003144 break;
3145 }
Fangrui Song050229d2018-11-24 00:14:31 +00003146 Result.AddTypedTextChunk(OperatorName);
3147 break;
3148 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003149
Douglas Gregor0212fd72010-09-21 16:06:22 +00003150 case DeclarationName::Identifier:
3151 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003152 case DeclarationName::CXXDestructorName:
3153 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003154 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003155 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003156 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003157
Richard Smith35845152017-02-07 01:37:30 +00003158 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003159 case DeclarationName::CXXUsingDirective:
3160 case DeclarationName::ObjCZeroArgSelector:
3161 case DeclarationName::ObjCOneArgSelector:
3162 case DeclarationName::ObjCMultiArgSelector:
3163 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003164
Douglas Gregor0212fd72010-09-21 16:06:22 +00003165 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003166 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003167 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003168 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003169 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003170 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003171 Record = InjectedTy->getDecl();
3172 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003173 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003174 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003175 break;
3176 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003177
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003178 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003179 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003180 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003181 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003182 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003183 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003184 }
3185 break;
3186 }
3187 }
3188}
3189
Fangrui Song050229d2018-11-24 00:14:31 +00003190CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3191 Sema &S, const CodeCompletionContext &CCContext,
3192 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3193 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003194 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3195 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003196}
3197
Eric Liu00f43c92018-07-06 09:43:57 +00003198CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3199 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3200 CodeCompletionTUInfo &CCTUInfo) {
3201 assert(Kind == RK_Macro);
3202 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3203 const MacroInfo *MI = PP.getMacroInfo(Macro);
3204 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3205
3206 if (!MI || !MI->isFunctionLike())
3207 return Result.TakeString();
3208
3209 // Format a function-like macro with placeholders for the arguments.
3210 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3211 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3212
3213 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3214 if (MI->isC99Varargs()) {
3215 --AEnd;
3216
3217 if (A == AEnd) {
3218 Result.AddPlaceholderChunk("...");
3219 }
3220 }
3221
3222 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3223 if (A != MI->param_begin())
3224 Result.AddChunk(CodeCompletionString::CK_Comma);
3225
3226 if (MI->isVariadic() && (A + 1) == AEnd) {
3227 SmallString<32> Arg = (*A)->getName();
3228 if (MI->isC99Varargs())
3229 Arg += ", ...";
3230 else
3231 Arg += "...";
3232 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3233 break;
3234 }
3235
3236 // Non-variadic macros are simple.
3237 Result.AddPlaceholderChunk(
3238 Result.getAllocator().CopyString((*A)->getName()));
3239 }
3240 Result.AddChunk(CodeCompletionString::CK_RightParen);
3241 return Result.TakeString();
3242}
3243
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003244/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003245/// result.
3246///
3247/// \returns Either a new, heap-allocated code completion string describing
3248/// how to use this result, or NULL to indicate that the string or name of the
3249/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003250CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3251 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3252 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3253 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003254 if (Kind == RK_Macro)
3255 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3256
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003257 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003258
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003259 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003260 if (Kind == RK_Pattern) {
3261 Pattern->Priority = Priority;
3262 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003263
Douglas Gregor78254c82012-03-27 23:34:16 +00003264 if (Declaration) {
3265 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003266 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003267 if (const RawComment *RC =
3268 getPatternCompletionComment(Ctx, Declaration)) {
3269 Result.addBriefComment(RC->getBriefText(Ctx));
3270 Pattern->BriefComment = Result.getBriefComment();
3271 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003272 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003273
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003274 return Pattern;
3275 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003276
Douglas Gregorf09935f2009-12-01 05:55:20 +00003277 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003278 Result.AddTypedTextChunk(Keyword);
3279 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003280 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003281 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003282 return createCodeCompletionStringForDecl(
3283 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003284}
3285
Ilya Biryukovcabab292019-05-24 10:18:39 +00003286static void printOverrideString(const CodeCompletionString &CCS,
3287 std::string &BeforeName,
3288 std::string &NameAndSignature) {
3289 bool SeenTypedChunk = false;
3290 for (auto &Chunk : CCS) {
3291 if (Chunk.Kind == CodeCompletionString::CK_Optional) {
3292 assert(SeenTypedChunk && "optional parameter before name");
3293 // Note that we put all chunks inside into NameAndSignature.
3294 printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature);
3295 continue;
3296 }
3297 SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText;
3298 if (SeenTypedChunk)
3299 NameAndSignature += Chunk.Text;
3300 else
3301 BeforeName += Chunk.Text;
3302 }
3303}
3304
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003305CodeCompletionString *
3306CodeCompletionResult::createCodeCompletionStringForOverride(
3307 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3308 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3309 PrintingPolicy &Policy) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003310 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3311 /*IncludeBriefComments=*/false,
3312 CCContext, Policy);
Ilya Biryukovcabab292019-05-24 10:18:39 +00003313 std::string BeforeName;
3314 std::string NameAndSignature;
3315 // For overrides all chunks go into the result, none are informative.
3316 printOverrideString(*CCS, BeforeName, NameAndSignature);
3317 NameAndSignature += " override";
3318
3319 Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));
3320 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3321 Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003322 return Result.TakeString();
3323}
3324
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003325// FIXME: Right now this works well with lambdas. Add support for other functor
3326// types like std::function.
3327static const NamedDecl *extractFunctorCallOperator(const NamedDecl *ND) {
3328 const auto *VD = dyn_cast<VarDecl>(ND);
3329 if (!VD)
3330 return nullptr;
3331 const auto *RecordDecl = VD->getType()->getAsCXXRecordDecl();
3332 if (!RecordDecl || !RecordDecl->isLambda())
3333 return nullptr;
3334 return RecordDecl->getLambdaCallOperator();
3335}
3336
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003337CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3338 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3339 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3340 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003341 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003342 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003343
3344 if (IncludeBriefComments) {
3345 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003346 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003347 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003348 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003349 }
3350
Douglas Gregor9eb77012009-11-07 00:00:49 +00003351 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003352 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003353 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003354 Result.AddTextChunk("::");
3355 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003356 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003357
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003358 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3359 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003360
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003361 auto AddFunctionTypeAndResult = [&](const FunctionDecl *Function) {
3362 AddResultTypeChunk(Ctx, Policy, Function, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003363 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003364 Ctx, Policy);
3365 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003366 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003367 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003368 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003369 AddFunctionTypeQualsToCompletionString(Result, Function);
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003370 };
3371
3372 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
3373 AddFunctionTypeAndResult(Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003374 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003375 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003376
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003377 if (const auto *CallOperator =
3378 dyn_cast_or_null<FunctionDecl>(extractFunctorCallOperator(ND))) {
3379 AddFunctionTypeAndResult(CallOperator);
3380 return Result.TakeString();
3381 }
3382
3383 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
3384
Fangrui Song050229d2018-11-24 00:14:31 +00003385 if (const FunctionTemplateDecl *FunTmpl =
3386 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003387 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003388 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003389 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003390 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003391
Douglas Gregor3545ff42009-09-21 16:56:56 +00003392 // Figure out which template parameters are deduced (or have default
3393 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003394 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003395 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003396 unsigned LastDeducibleArgument;
3397 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3398 --LastDeducibleArgument) {
3399 if (!Deduced[LastDeducibleArgument - 1]) {
3400 // C++0x: Figure out if the template argument has a default. If so,
3401 // the user doesn't need to type this argument.
3402 // FIXME: We need to abstract template parameters better!
3403 bool HasDefaultArg = false;
3404 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003405 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003406 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3407 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003408 else if (NonTypeTemplateParmDecl *NTTP =
3409 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003410 HasDefaultArg = NTTP->hasDefaultArgument();
3411 else {
3412 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003413 HasDefaultArg =
3414 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003415 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003416
Douglas Gregor3545ff42009-09-21 16:56:56 +00003417 if (!HasDefaultArg)
3418 break;
3419 }
3420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003421
Douglas Gregor3545ff42009-09-21 16:56:56 +00003422 if (LastDeducibleArgument) {
3423 // Some of the function template arguments cannot be deduced from a
3424 // function call, so we introduce an explicit template argument list
3425 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003426 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003427 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003428 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003429 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003430 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003431
Douglas Gregor3545ff42009-09-21 16:56:56 +00003432 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003433 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003434 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003435 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003436 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003437 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003438 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003439
Fangrui Song050229d2018-11-24 00:14:31 +00003440 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003441 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003442 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003443 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003444 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003445 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003446 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003447 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003448 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003449 }
Kirill Bobyrev7f0dcf62019-11-22 12:48:06 +01003450
Fangrui Song050229d2018-11-24 00:14:31 +00003451 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003452 Selector Sel = Method->getSelector();
3453 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003454 Result.AddTypedTextChunk(
3455 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003456 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003457 }
3458
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003459 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003460 SelName += ':';
3461 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003462 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003463 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003464 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003465
Douglas Gregor1b605f72009-11-19 01:08:35 +00003466 // If there is only one parameter, and we're past it, add an empty
3467 // typed-text chunk since there is nothing to type.
3468 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003469 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003470 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003471 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003472 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003473 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003474 P != PEnd; (void)++P, ++Idx) {
3475 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003476 std::string Keyword;
3477 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003478 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003479 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003480 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003481 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003482 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003483 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003484 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003485 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003486 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003487
Douglas Gregor1b605f72009-11-19 01:08:35 +00003488 // If we're before the starting parameter, skip the placeholder.
3489 if (Idx < StartParameter)
3490 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003491
3492 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003493 QualType ParamType = (*P)->getType();
3494 Optional<ArrayRef<QualType>> ObjCSubsts;
3495 if (!CCContext.getBaseType().isNull())
3496 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3497
3498 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3499 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003500 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003501 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003502 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003503 ParamType = ParamType.substObjCTypeArgs(
3504 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003505 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003506 ParamType);
3507 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003508 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003509 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003510 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003511 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003512
Douglas Gregor400f5972010-08-31 05:13:43 +00003513 if (Method->isVariadic() && (P + 1) == PEnd)
3514 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003515
Douglas Gregor95887f92010-07-08 23:20:03 +00003516 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003517 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003518 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003519 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003520 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003521 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003522 }
3523
Douglas Gregor04c5f972009-12-23 00:21:46 +00003524 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003525 if (Method->param_size() == 0) {
3526 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003527 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003528 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003529 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003530 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003531 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003532 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003533
Richard Smith20e883e2015-04-29 23:20:19 +00003534 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003535 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003536
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003537 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003538 }
3539
Douglas Gregorf09935f2009-12-01 05:55:20 +00003540 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003541 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003542 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003543
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003544 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003545 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003546 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003547}
3548
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003549const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3550 const NamedDecl *ND) {
3551 if (!ND)
3552 return nullptr;
3553 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3554 return RC;
3555
3556 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003557 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003558 if (!M)
3559 return nullptr;
3560 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3561 if (!PDecl)
3562 return nullptr;
3563
3564 return Ctx.getRawCommentForAnyRedecl(PDecl);
3565}
3566
3567const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3568 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003569 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003570 if (!M || !M->isPropertyAccessor())
3571 return nullptr;
3572
3573 // Provide code completion comment for self.GetterName where
3574 // GetterName is the getter method for a property with name
3575 // different from the property name (declared via a property
3576 // getter attribute.
3577 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3578 if (!PDecl)
3579 return nullptr;
3580 if (PDecl->getGetterName() == M->getSelector() &&
3581 PDecl->getIdentifier() != M->getIdentifier()) {
3582 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3583 return RC;
3584 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3585 return RC;
3586 }
3587 return nullptr;
3588}
3589
3590const RawComment *clang::getParameterComment(
3591 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003592 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003593 auto FDecl = Result.getFunction();
3594 if (!FDecl)
3595 return nullptr;
3596 if (ArgIndex < FDecl->getNumParams())
3597 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3598 return nullptr;
3599}
3600
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003601/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003602/// string.
3603static void AddOverloadParameterChunks(ASTContext &Context,
3604 const PrintingPolicy &Policy,
3605 const FunctionDecl *Function,
3606 const FunctionProtoType *Prototype,
3607 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003608 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003609 bool InOptional = false) {
3610 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003611 unsigned NumParams =
3612 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003613
3614 for (unsigned P = Start; P != NumParams; ++P) {
3615 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3616 // When we see an optional default argument, put that argument and
3617 // the remaining default arguments into a new, optional string.
3618 CodeCompletionBuilder Opt(Result.getAllocator(),
3619 Result.getCodeCompletionTUInfo());
3620 if (!FirstParameter)
3621 Opt.AddChunk(CodeCompletionString::CK_Comma);
3622 // Optional sections are nested.
3623 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3624 CurrentArg, P, /*InOptional=*/true);
3625 Result.AddOptionalChunk(Opt.TakeString());
3626 return;
3627 }
3628
3629 if (FirstParameter)
3630 FirstParameter = false;
3631 else
3632 Result.AddChunk(CodeCompletionString::CK_Comma);
3633
3634 InOptional = false;
3635
3636 // Format the placeholder string.
3637 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003638 if (Function) {
3639 const ParmVarDecl *Param = Function->getParamDecl(P);
3640 Placeholder = FormatFunctionParameter(Policy, Param);
3641 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003642 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3643 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003644 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003645 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003646 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003647
3648 if (P == CurrentArg)
3649 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003650 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003651 else
3652 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3653 }
3654
3655 if (Prototype && Prototype->isVariadic()) {
3656 CodeCompletionBuilder Opt(Result.getAllocator(),
3657 Result.getCodeCompletionTUInfo());
3658 if (!FirstParameter)
3659 Opt.AddChunk(CodeCompletionString::CK_Comma);
3660
3661 if (CurrentArg < NumParams)
3662 Opt.AddPlaceholderChunk("...");
3663 else
3664 Opt.AddCurrentParameterChunk("...");
3665
3666 Result.AddOptionalChunk(Opt.TakeString());
3667 }
3668}
3669
Douglas Gregorf0f51982009-09-23 00:34:09 +00003670CodeCompletionString *
3671CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003672 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3673 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003674 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Sam McCallfa3b87f2019-11-15 14:52:04 +01003675 // Show signatures of constructors as they are declared:
3676 // vector(int n) rather than vector<string>(int n)
3677 // This is less noisy without being less clear, and avoids tricky cases.
3678 Policy.SuppressTemplateArgsInCXXConstructors = true;
John McCall31168b02011-06-15 23:02:42 +00003679
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003680 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003681 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3682 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003683 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003684 const FunctionProtoType *Proto =
3685 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003686 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003687 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003688 // highlighted ellipsis.
3689 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003690 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003691 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003692 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3693 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3694 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003695 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003696 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003697
3698 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003699 if (IncludeBriefComments) {
3700 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003701 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003702 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003703 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003704 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003705 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003706 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003707 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003708 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003709 }
Alp Toker314cc812014-01-25 16:55:45 +00003710
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003711 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003712 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3713 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003714 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003715
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003716 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003717}
3718
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003719unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003720 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003721 bool PreferredTypeIsPointer) {
3722 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003723
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003724 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003725 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003726 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003727 Priority = CCP_Constant;
3728 if (PreferredTypeIsPointer)
3729 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003730 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003731 // Treat "YES", "NO", "true", and "false" as constants.
3732 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3733 MacroName.equals("true") || MacroName.equals("false"))
3734 Priority = CCP_Constant;
3735 // Treat "bool" as a type.
3736 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003737 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003738
Douglas Gregor6e240332010-08-16 16:18:59 +00003739 return Priority;
3740}
3741
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003742CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003743 if (!D)
3744 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003745
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003746 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003747 case Decl::Enum:
3748 return CXCursor_EnumDecl;
3749 case Decl::EnumConstant:
3750 return CXCursor_EnumConstantDecl;
3751 case Decl::Field:
3752 return CXCursor_FieldDecl;
3753 case Decl::Function:
3754 return CXCursor_FunctionDecl;
3755 case Decl::ObjCCategory:
3756 return CXCursor_ObjCCategoryDecl;
3757 case Decl::ObjCCategoryImpl:
3758 return CXCursor_ObjCCategoryImplDecl;
3759 case Decl::ObjCImplementation:
3760 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003761
Fangrui Song050229d2018-11-24 00:14:31 +00003762 case Decl::ObjCInterface:
3763 return CXCursor_ObjCInterfaceDecl;
3764 case Decl::ObjCIvar:
3765 return CXCursor_ObjCIvarDecl;
3766 case Decl::ObjCMethod:
3767 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3768 ? CXCursor_ObjCInstanceMethodDecl
3769 : CXCursor_ObjCClassMethodDecl;
3770 case Decl::CXXMethod:
3771 return CXCursor_CXXMethod;
3772 case Decl::CXXConstructor:
3773 return CXCursor_Constructor;
3774 case Decl::CXXDestructor:
3775 return CXCursor_Destructor;
3776 case Decl::CXXConversion:
3777 return CXCursor_ConversionFunction;
3778 case Decl::ObjCProperty:
3779 return CXCursor_ObjCPropertyDecl;
3780 case Decl::ObjCProtocol:
3781 return CXCursor_ObjCProtocolDecl;
3782 case Decl::ParmVar:
3783 return CXCursor_ParmDecl;
3784 case Decl::Typedef:
3785 return CXCursor_TypedefDecl;
3786 case Decl::TypeAlias:
3787 return CXCursor_TypeAliasDecl;
3788 case Decl::TypeAliasTemplate:
3789 return CXCursor_TypeAliasTemplateDecl;
3790 case Decl::Var:
3791 return CXCursor_VarDecl;
3792 case Decl::Namespace:
3793 return CXCursor_Namespace;
3794 case Decl::NamespaceAlias:
3795 return CXCursor_NamespaceAlias;
3796 case Decl::TemplateTypeParm:
3797 return CXCursor_TemplateTypeParameter;
3798 case Decl::NonTypeTemplateParm:
3799 return CXCursor_NonTypeTemplateParameter;
3800 case Decl::TemplateTemplateParm:
3801 return CXCursor_TemplateTemplateParameter;
3802 case Decl::FunctionTemplate:
3803 return CXCursor_FunctionTemplate;
3804 case Decl::ClassTemplate:
3805 return CXCursor_ClassTemplate;
3806 case Decl::AccessSpec:
3807 return CXCursor_CXXAccessSpecifier;
3808 case Decl::ClassTemplatePartialSpecialization:
3809 return CXCursor_ClassTemplatePartialSpecialization;
3810 case Decl::UsingDirective:
3811 return CXCursor_UsingDirective;
3812 case Decl::StaticAssert:
3813 return CXCursor_StaticAssert;
3814 case Decl::Friend:
3815 return CXCursor_FriendDecl;
3816 case Decl::TranslationUnit:
3817 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003818
Fangrui Song050229d2018-11-24 00:14:31 +00003819 case Decl::Using:
3820 case Decl::UnresolvedUsingValue:
3821 case Decl::UnresolvedUsingTypename:
3822 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003823
Fangrui Song050229d2018-11-24 00:14:31 +00003824 case Decl::ObjCPropertyImpl:
3825 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3826 case ObjCPropertyImplDecl::Dynamic:
3827 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003828
Fangrui Song050229d2018-11-24 00:14:31 +00003829 case ObjCPropertyImplDecl::Synthesize:
3830 return CXCursor_ObjCSynthesizeDecl;
3831 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003832 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003833
3834 case Decl::Import:
3835 return CXCursor_ModuleImportDecl;
3836
3837 case Decl::ObjCTypeParam:
3838 return CXCursor_TemplateTypeParameter;
3839
3840 default:
3841 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3842 switch (TD->getTagKind()) {
3843 case TTK_Interface: // fall through
3844 case TTK_Struct:
3845 return CXCursor_StructDecl;
3846 case TTK_Class:
3847 return CXCursor_ClassDecl;
3848 case TTK_Union:
3849 return CXCursor_UnionDecl;
3850 case TTK_Enum:
3851 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003852 }
Fangrui Song050229d2018-11-24 00:14:31 +00003853 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003854 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003855
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003856 return CXCursor_UnexposedDecl;
3857}
3858
Douglas Gregor55b037b2010-07-08 20:55:51 +00003859static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003860 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003861 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003862 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003863
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003864 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003865
Eric Liu88de9f62018-09-19 09:34:55 +00003866 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3867 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003868 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003869 auto MD = PP.getMacroDefinition(M->first);
3870 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003871 MacroInfo *MI = MD.getMacroInfo();
3872 if (MI && MI->isUsedForHeaderGuard())
3873 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003874
Eric Liud485df12018-09-05 14:59:17 +00003875 Results.AddResult(
3876 Result(M->first, MI,
3877 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3878 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003879 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003880 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003881
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003882 Results.ExitScope();
3883}
3884
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003885static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003886 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003887 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003888
Douglas Gregorce0e8562010-08-23 21:54:33 +00003889 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003890
Douglas Gregorce0e8562010-08-23 21:54:33 +00003891 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3892 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003893 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003894 Results.AddResult(Result("__func__", CCP_Constant));
3895 Results.ExitScope();
3896}
3897
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003898static void HandleCodeCompleteResults(Sema *S,
3899 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003900 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003901 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003902 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003903 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003904 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003905}
3906
Ilya Biryukov41109672018-12-13 15:36:32 +00003907static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003908mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003909 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003910 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003911 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003912
John McCallfaf5fb42010-08-26 23:41:50 +00003913 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003914 return CodeCompletionContext::CCC_ClassStructUnion;
3915
John McCallfaf5fb42010-08-26 23:41:50 +00003916 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003917 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003918
John McCallfaf5fb42010-08-26 23:41:50 +00003919 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003920 return CodeCompletionContext::CCC_ObjCImplementation;
3921
John McCallfaf5fb42010-08-26 23:41:50 +00003922 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003923 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003924
John McCallfaf5fb42010-08-26 23:41:50 +00003925 case Sema::PCC_Template:
3926 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003927 if (S.CurContext->isFileContext())
3928 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003929 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003930 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003931 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003932
John McCallfaf5fb42010-08-26 23:41:50 +00003933 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003934 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003935
John McCallfaf5fb42010-08-26 23:41:50 +00003936 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003937 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003938 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003939 return CodeCompletionContext::CCC_ParenthesizedExpression;
3940 else
3941 return CodeCompletionContext::CCC_Expression;
3942
3943 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003944 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003945 case Sema::PCC_Condition:
3946 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3947 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003948
John McCallfaf5fb42010-08-26 23:41:50 +00003949 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003950 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003951
John McCallfaf5fb42010-08-26 23:41:50 +00003952 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003953 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003954
3955 case Sema::PCC_ParenthesizedExpression:
3956 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003957
Douglas Gregor80039242011-02-15 20:33:25 +00003958 case Sema::PCC_LocalDeclarationSpecifiers:
3959 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003960 }
David Blaikie8a40f702012-01-17 06:56:22 +00003961
3962 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003963}
3964
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003965/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003966/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003967/// overridden function as well as adding new functionality.
3968///
3969/// \param S The semantic analysis object for which we are generating results.
3970///
3971/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003972/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003973static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3974 ResultBuilder &Results) {
3975 // Look through blocks.
3976 DeclContext *CurContext = S.CurContext;
3977 while (isa<BlockDecl>(CurContext))
3978 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003979
Douglas Gregorac322ec2010-08-27 21:18:54 +00003980 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3981 if (!Method || !Method->isVirtual())
3982 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003983
3984 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003985 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003986 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003987 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003988 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003989
Douglas Gregor75acd922011-09-27 23:30:47 +00003990 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003991 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003992 CodeCompletionBuilder Builder(Results.getAllocator(),
3993 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003994 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3995 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003996
Douglas Gregorac322ec2010-08-27 21:18:54 +00003997 // If we need a nested-name-specifier, add one now.
3998 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003999 NestedNameSpecifier *NNS = getRequiredQualification(
4000 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00004001 if (NNS) {
4002 std::string Str;
4003 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00004004 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004005 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004006 }
4007 } else if (!InContext->Equals(Overridden->getDeclContext()))
4008 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004009
Fangrui Song050229d2018-11-24 00:14:31 +00004010 Builder.AddTypedTextChunk(
4011 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004012 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004013 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00004014 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00004015 if (FirstParam)
4016 FirstParam = false;
4017 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004018 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004019
Aaron Ballman43b68be2014-03-07 17:50:17 +00004020 Builder.AddPlaceholderChunk(
4021 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004022 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004023 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00004024 Results.AddResult(CodeCompletionResult(
4025 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
4026 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004027 Results.Ignore(Overridden);
4028 }
4029}
4030
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004031void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00004032 ModuleIdPath Path) {
4033 typedef CodeCompletionResult Result;
4034 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004035 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00004036 CodeCompletionContext::CCC_Other);
4037 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004038
Douglas Gregor07f43572012-01-29 18:15:03 +00004039 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004040 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00004041 typedef CodeCompletionResult Result;
4042 if (Path.empty()) {
4043 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00004044 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00004045 PP.getHeaderSearchInfo().collectAllModules(Modules);
4046 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
4047 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004048 Builder.getAllocator().CopyString(Modules[I]->Name));
4049 Results.AddResult(Result(
4050 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4051 Modules[I]->isAvailable() ? CXAvailability_Available
4052 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004053 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00004054 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00004055 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00004056 Module *Mod =
4057 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
4058 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00004059 // Enumerate submodules.
4060 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004061 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00004062 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00004063 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004064
Douglas Gregor07f43572012-01-29 18:15:03 +00004065 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004066 Builder.getAllocator().CopyString((*Sub)->Name));
4067 Results.AddResult(Result(
4068 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4069 (*Sub)->isAvailable() ? CXAvailability_Available
4070 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004071 }
4072 }
4073 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004074 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00004075 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004076 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00004077}
4078
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004079void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004080 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004081 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004082 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004083 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004084 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004085
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004086 // Determine how to filter results, e.g., so that the names of
4087 // values (functions, enumerators, function templates, etc.) are
4088 // only allowed where we can have an expression.
4089 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004090 case PCC_Namespace:
4091 case PCC_Class:
4092 case PCC_ObjCInterface:
4093 case PCC_ObjCImplementation:
4094 case PCC_ObjCInstanceVariableList:
4095 case PCC_Template:
4096 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004097 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004098 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004099 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4100 break;
4101
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004102 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00004103 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00004104 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004105 case PCC_ForInit:
4106 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00004107 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00004108 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4109 else
4110 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004111
David Blaikiebbafb8a2012-03-11 07:00:24 +00004112 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00004113 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004114 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004115
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004116 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00004117 // Unfiltered
4118 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004119 }
4120
Douglas Gregor9be0ed42010-08-26 16:36:48 +00004121 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004122 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00004123 auto ThisType = getCurrentThisType();
4124 if (!ThisType.isNull())
Sam McCall3dea5272019-06-10 15:17:52 +00004125 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(),
4126 VK_LValue);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004127
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004128 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004129 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004130 CodeCompleter->includeGlobals(),
4131 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00004132
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004133 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00004134 Results.ExitScope();
4135
Douglas Gregorce0e8562010-08-23 21:54:33 +00004136 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00004137 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004138 case PCC_Expression:
4139 case PCC_Statement:
4140 case PCC_RecoveryInFunction:
4141 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004142 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004143 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004144
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004145 case PCC_Namespace:
4146 case PCC_Class:
4147 case PCC_ObjCInterface:
4148 case PCC_ObjCImplementation:
4149 case PCC_ObjCInstanceVariableList:
4150 case PCC_Template:
4151 case PCC_MemberTemplate:
4152 case PCC_ForInit:
4153 case PCC_Condition:
4154 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004155 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004156 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00004157 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004158
Douglas Gregor9eb77012009-11-07 00:00:49 +00004159 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004160 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004161
Douglas Gregor50832e02010-09-20 22:39:41 +00004162 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004163 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00004164}
4165
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004166static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004167 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004168 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00004169 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004170 ResultBuilder &Results);
4171
4172void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
4173 bool AllowNonIdentifiers,
4174 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00004175 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004176 ResultBuilder Results(
4177 *this, CodeCompleter->getAllocator(),
4178 CodeCompleter->getCodeCompletionTUInfo(),
4179 AllowNestedNameSpecifiers
4180 // FIXME: Try to separate codepath leading here to deduce whether we
4181 // need an existing symbol or a new one.
4182 ? CodeCompletionContext::CCC_SymbolOrNewName
4183 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004184 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004185
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004186 // Type qualifiers can come after names.
4187 Results.AddResult(Result("const"));
4188 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004189 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004190 Results.AddResult(Result("restrict"));
4191
David Blaikiebbafb8a2012-03-11 07:00:24 +00004192 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004193 if (getLangOpts().CPlusPlus11 &&
4194 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4195 DS.getTypeSpecType() == DeclSpec::TST_struct))
4196 Results.AddResult("final");
4197
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004198 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004199 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004200 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004201
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004202 // Add nested-name-specifiers.
4203 if (AllowNestedNameSpecifiers) {
4204 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004205 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004206 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4207 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004208 CodeCompleter->includeGlobals(),
4209 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004210 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004211 }
4212 }
4213 Results.ExitScope();
4214
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004215 // If we're in a context where we might have an expression (rather than a
4216 // declaration), and what we've seen so far is an Objective-C type that could
4217 // be a receiver of a class message, this may be a class message send with
4218 // the initial opening bracket '[' missing. Add appropriate completions.
4219 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004220 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004221 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004222 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4223 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004224 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004225 (S->getFlags() & Scope::DeclScope) != 0 &&
4226 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004227 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4228 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004229 ParsedType T = DS.getRepAsType();
4230 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004231 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004232 }
4233
Douglas Gregor56ccce02010-08-24 04:59:56 +00004234 // Note that we intentionally suppress macro results here, since we do not
4235 // encourage using macros to produce the names of entities.
4236
Fangrui Song050229d2018-11-24 00:14:31 +00004237 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004238 Results.data(), Results.size());
4239}
4240
Douglas Gregor68762e72010-08-23 21:17:50 +00004241struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004242 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4243 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004244 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004245 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004246
Douglas Gregor68762e72010-08-23 21:17:50 +00004247 QualType PreferredType;
4248 bool IntegralConstantExpression;
4249 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004250 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004251 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004252};
4253
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004254namespace {
4255/// Information that allows to avoid completing redundant enumerators.
4256struct CoveredEnumerators {
4257 llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
4258 NestedNameSpecifier *SuggestedQualifier = nullptr;
4259};
4260} // namespace
4261
4262static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
4263 EnumDecl *Enum, DeclContext *CurContext,
4264 const CoveredEnumerators &Enumerators) {
4265 NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
4266 if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
4267 // If there are no prior enumerators in C++, check whether we have to
4268 // qualify the names of the enumerators that we suggest, because they
4269 // may not be visible in this scope.
4270 Qualifier = getRequiredQualification(Context, CurContext, Enum);
4271 }
4272
4273 Results.EnterNewScope();
4274 for (auto *E : Enum->enumerators()) {
4275 if (Enumerators.Seen.count(E))
4276 continue;
4277
4278 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
4279 Results.AddResult(R, CurContext, nullptr, false);
4280 }
4281 Results.ExitScope();
4282}
4283
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004284/// Try to find a corresponding FunctionProtoType for function-like types (e.g.
4285/// function pointers, std::function, etc).
4286static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) {
4287 assert(!T.isNull());
4288 // Try to extract first template argument from std::function<> and similar.
4289 // Note we only handle the sugared types, they closely match what users wrote.
4290 // We explicitly choose to not handle ClassTemplateSpecializationDecl.
4291 if (auto *Specialization = T->getAs<TemplateSpecializationType>()) {
4292 if (Specialization->getNumArgs() != 1)
4293 return nullptr;
4294 const TemplateArgument &Argument = Specialization->getArg(0);
4295 if (Argument.getKind() != TemplateArgument::Type)
4296 return nullptr;
4297 return Argument.getAsType()->getAs<FunctionProtoType>();
4298 }
4299 // Handle other cases.
4300 if (T->isPointerType())
4301 T = T->getPointeeType();
4302 return T->getAs<FunctionProtoType>();
4303}
4304
4305/// Adds a pattern completion for a lambda expression with the specified
4306/// parameter types and placeholders for parameter names.
4307static void AddLambdaCompletion(ResultBuilder &Results,
4308 llvm::ArrayRef<QualType> Parameters,
4309 const LangOptions &LangOpts) {
Ilya Biryukovfd11a5f2019-05-23 16:39:26 +00004310 if (!Results.includeCodePatterns())
4311 return;
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004312 CodeCompletionBuilder Completion(Results.getAllocator(),
4313 Results.getCodeCompletionTUInfo());
4314 // [](<parameters>) {}
4315 Completion.AddChunk(CodeCompletionString::CK_LeftBracket);
4316 Completion.AddPlaceholderChunk("=");
4317 Completion.AddChunk(CodeCompletionString::CK_RightBracket);
4318 if (!Parameters.empty()) {
4319 Completion.AddChunk(CodeCompletionString::CK_LeftParen);
4320 bool First = true;
4321 for (auto Parameter : Parameters) {
4322 if (!First)
4323 Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma);
4324 else
4325 First = false;
4326
4327 constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!";
4328 std::string Type = NamePlaceholder;
4329 Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts));
4330 llvm::StringRef Prefix, Suffix;
4331 std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder);
4332 Prefix = Prefix.rtrim();
4333 Suffix = Suffix.ltrim();
4334
4335 Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix));
4336 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4337 Completion.AddPlaceholderChunk("parameter");
4338 Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix));
4339 };
4340 Completion.AddChunk(CodeCompletionString::CK_RightParen);
4341 }
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004342 Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004343 Completion.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004344 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004345 Completion.AddPlaceholderChunk("body");
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004346 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004347 Completion.AddChunk(CodeCompletionString::CK_RightBrace);
4348
4349 Results.AddResult(Completion.TakeString());
4350}
4351
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004352/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004353/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004354void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004355 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004356 ResultBuilder Results(
4357 *this, CodeCompleter->getAllocator(),
4358 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004359 CodeCompletionContext(
4360 Data.IsParenthesized
4361 ? CodeCompletionContext::CCC_ParenthesizedExpression
4362 : CodeCompletionContext::CCC_Expression,
4363 Data.PreferredType));
4364 auto PCC =
4365 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004366 if (Data.ObjCCollection)
4367 Results.setFilter(&ResultBuilder::IsObjCCollection);
4368 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004369 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004370 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004371 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4372 else
4373 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004374
4375 if (!Data.PreferredType.isNull())
4376 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004377
Douglas Gregor68762e72010-08-23 21:17:50 +00004378 // Ignore any declarations that we were told that we don't care about.
4379 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4380 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004381
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004382 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004383 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004384 CodeCompleter->includeGlobals(),
4385 CodeCompleter->loadExternal());
4386
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004387 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004388 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004389 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004390
Douglas Gregor55b037b2010-07-08 20:55:51 +00004391 bool PreferredTypeIsPointer = false;
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004392 if (!Data.PreferredType.isNull()) {
Fangrui Song050229d2018-11-24 00:14:31 +00004393 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4394 Data.PreferredType->isMemberPointerType() ||
4395 Data.PreferredType->isBlockPointerType();
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004396 if (Data.PreferredType->isEnumeralType()) {
4397 EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();
4398 if (auto *Def = Enum->getDefinition())
4399 Enum = Def;
4400 // FIXME: collect covered enumerators in cases like:
4401 // if (x == my_enum::one) { ... } else if (x == ^) {}
4402 AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators());
4403 }
4404 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004405
Fangrui Song050229d2018-11-24 00:14:31 +00004406 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004407 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004408 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004409
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004410 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004411 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4412 PreferredTypeIsPointer);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004413
4414 // Complete a lambda expression when preferred type is a function.
4415 if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) {
4416 if (const FunctionProtoType *F =
4417 TryDeconstructFunctionLike(Data.PreferredType))
4418 AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts());
4419 }
4420
Eric Liuf5ba09f2018-07-04 10:01:18 +00004421 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4422 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004423}
4424
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004425void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4426 bool IsParenthesized) {
4427 return CodeCompleteExpression(
4428 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004429}
4430
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004431void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4432 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004433 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004434 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004435 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004436 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004437}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004438
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004439/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004440/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004441typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004442
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004443/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004444static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4445 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4446 if (Interface->hasDefinition())
4447 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004448
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004449 return Interface;
4450 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004451
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004452 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4453 if (Protocol->hasDefinition())
4454 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004455
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004456 return Protocol;
4457 }
4458 return Container;
4459}
4460
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004461/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004462/// declaration \p BD.
4463static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4464 CodeCompletionBuilder &Builder,
4465 const NamedDecl *BD,
4466 const FunctionTypeLoc &BlockLoc,
4467 const FunctionProtoTypeLoc &BlockProtoLoc) {
4468 Builder.AddResultTypeChunk(
4469 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4470 Policy, Builder.getAllocator()));
4471
4472 AddTypedNameChunk(Context, Policy, BD, Builder);
4473 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4474
4475 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4476 Builder.AddPlaceholderChunk("...");
4477 } else {
4478 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4479 if (I)
4480 Builder.AddChunk(CodeCompletionString::CK_Comma);
4481
4482 // Format the placeholder string.
4483 std::string PlaceholderStr =
4484 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4485
4486 if (I == N - 1 && BlockProtoLoc &&
4487 BlockProtoLoc.getTypePtr()->isVariadic())
4488 PlaceholderStr += ", ...";
4489
4490 // Add the placeholder string.
4491 Builder.AddPlaceholderChunk(
4492 Builder.getAllocator().CopyString(PlaceholderStr));
4493 }
4494 }
4495
4496 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4497}
4498
Fangrui Song050229d2018-11-24 00:14:31 +00004499static void
4500AddObjCProperties(const CodeCompletionContext &CCContext,
4501 ObjCContainerDecl *Container, bool AllowCategories,
4502 bool AllowNullaryMethods, DeclContext *CurContext,
4503 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4504 bool IsBaseExprStatement = false,
4505 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004506 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004507
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004508 // Retrieve the definition.
4509 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004510
Douglas Gregor9291bad2009-11-18 01:29:26 +00004511 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004512 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004513 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004514 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004515
Alex Lorenzbaef8022016-11-09 13:43:18 +00004516 // FIXME: Provide block invocation completion for non-statement
4517 // expressions.
4518 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4519 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004520 Result R = Result(P, Results.getBasePriority(P), nullptr);
4521 if (!InOriginalClass)
4522 setInBaseClass(R);
4523 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004524 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004525 }
4526
4527 // Block setter and invocation completion is provided only when we are able
4528 // to find the FunctionProtoTypeLoc with parameter names for the block.
4529 FunctionTypeLoc BlockLoc;
4530 FunctionProtoTypeLoc BlockProtoLoc;
4531 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4532 BlockProtoLoc);
4533 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004534 Result R = Result(P, Results.getBasePriority(P), nullptr);
4535 if (!InOriginalClass)
4536 setInBaseClass(R);
4537 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004538 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004539 }
4540
4541 // The default completion result for block properties should be the block
4542 // invocation completion when the base expression is a statement.
4543 CodeCompletionBuilder Builder(Results.getAllocator(),
4544 Results.getCodeCompletionTUInfo());
4545 AddObjCBlockCall(Container->getASTContext(),
4546 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4547 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004548 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4549 if (!InOriginalClass)
4550 setInBaseClass(R);
4551 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004552
4553 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004554 // statement and the block property is mutable.
4555 if (!P->isReadOnly()) {
4556 CodeCompletionBuilder Builder(Results.getAllocator(),
4557 Results.getCodeCompletionTUInfo());
4558 AddResultTypeChunk(Container->getASTContext(),
4559 getCompletionPrintingPolicy(Results.getSema()), P,
4560 CCContext.getBaseType(), Builder);
4561 Builder.AddTypedTextChunk(
4562 Results.getAllocator().CopyString(P->getName()));
4563 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004564
Alex Lorenzbaef8022016-11-09 13:43:18 +00004565 std::string PlaceholderStr = formatBlockPlaceholder(
4566 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4567 BlockProtoLoc, /*SuppressBlockName=*/true);
4568 // Add the placeholder string.
4569 Builder.AddPlaceholderChunk(
4570 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004571
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004572 // When completing blocks properties that return void the default
4573 // property completion result should show up before the setter,
4574 // otherwise the setter completion should show up before the default
4575 // property completion, as we normally want to use the result of the
4576 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004577 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004578 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004579 Results.getBasePriority(P) +
4580 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4581 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004582 : -CCD_BlockPropertySetter));
4583 if (!InOriginalClass)
4584 setInBaseClass(R);
4585 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004586 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004587 };
4588
4589 if (IsClassProperty) {
4590 for (const auto *P : Container->class_properties())
4591 AddProperty(P);
4592 } else {
4593 for (const auto *P : Container->instance_properties())
4594 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004595 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004596
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004597 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004598 if (AllowNullaryMethods) {
4599 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004600 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004601 // Adds a method result
4602 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4603 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4604 if (!Name)
4605 return;
4606 if (!AddedProperties.insert(Name).second)
4607 return;
4608 CodeCompletionBuilder Builder(Results.getAllocator(),
4609 Results.getCodeCompletionTUInfo());
4610 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4611 Builder.AddTypedTextChunk(
4612 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004613 Result R = Result(Builder.TakeString(), M,
4614 CCP_MemberDeclaration + CCD_MethodAsProperty);
4615 if (!InOriginalClass)
4616 setInBaseClass(R);
4617 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004618 };
4619
4620 if (IsClassProperty) {
4621 for (const auto *M : Container->methods()) {
4622 // Gather the class method that can be used as implicit property
4623 // getters. Methods with arguments or methods that return void aren't
4624 // added to the results as they can't be used as a getter.
4625 if (!M->getSelector().isUnarySelector() ||
4626 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4627 continue;
4628 AddMethod(M);
4629 }
4630 } else {
4631 for (auto *M : Container->methods()) {
4632 if (M->getSelector().isUnarySelector())
4633 AddMethod(M);
4634 }
Douglas Gregor95147142011-05-05 15:50:42 +00004635 }
4636 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004637
Douglas Gregor9291bad2009-11-18 01:29:26 +00004638 // Add properties in referenced protocols.
4639 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004640 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004641 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004642 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004643 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004644 /*InOriginalClass*/ false);
4645 } else if (ObjCInterfaceDecl *IFace =
4646 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004647 if (AllowCategories) {
4648 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004649 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004650 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004651 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004652 IsBaseExprStatement, IsClassProperty,
4653 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004654 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004655
Douglas Gregor9291bad2009-11-18 01:29:26 +00004656 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004657 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004658 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004659 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004660 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004661 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004662
Douglas Gregor9291bad2009-11-18 01:29:26 +00004663 // Look in the superclass.
4664 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004665 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004666 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004667 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004668 /*InOriginalClass*/ false);
4669 } else if (const auto *Category =
4670 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004671 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004672 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004673 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004674 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004675 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004676 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004677 }
4678}
4679
Sam McCall3dea5272019-06-10 15:17:52 +00004680static void AddRecordMembersCompletionResults(
4681 Sema &SemaRef, ResultBuilder &Results, Scope *S, QualType BaseType,
4682 ExprValueKind BaseKind, RecordDecl *RD, Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004683 // Indicate that we are performing a member access, and the cv-qualifiers
4684 // for the base object type.
Sam McCall3dea5272019-06-10 15:17:52 +00004685 Results.setObjectTypeQualifiers(BaseType.getQualifiers(), BaseKind);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004686
4687 // Access to a C/C++ class, struct, or union.
4688 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004689 std::vector<FixItHint> FixIts;
4690 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004691 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004692 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004693 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004694 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004695 /*IncludeDependentBases=*/true,
4696 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004697
4698 if (SemaRef.getLangOpts().CPlusPlus) {
4699 if (!Results.empty()) {
4700 // The "template" keyword can follow "->" or "." in the grammar.
4701 // However, we only want to suggest the template keyword if something
4702 // is dependent.
4703 bool IsDependent = BaseType->isDependentType();
4704 if (!IsDependent) {
4705 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4706 if (DeclContext *Ctx = DepScope->getEntity()) {
4707 IsDependent = Ctx->isDependentContext();
4708 break;
4709 }
4710 }
4711
4712 if (IsDependent)
4713 Results.AddResult(CodeCompletionResult("template"));
4714 }
4715 }
4716}
4717
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004718void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004719 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004720 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004721 bool IsBaseExprStatement,
4722 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004723 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004724 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004725
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004726 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4727 if (ConvertedBase.isInvalid())
4728 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004729 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4730
4731 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004732
4733 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004734 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004735 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004736 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004737
Douglas Gregor21325842011-07-07 16:03:39 +00004738 if (IsArrow) {
4739 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004740 } else {
4741 if (ConvertedBaseType->isObjCObjectPointerType() ||
4742 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004743 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004744 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004745 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4746 }
4747 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004748
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004749 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004750 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004751 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004752 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004753 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004754
Fangrui Song050229d2018-11-24 00:14:31 +00004755 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4756 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004757 if (!Base)
4758 return false;
4759
4760 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4761 if (ConvertedBase.isInvalid())
4762 return false;
4763 Base = ConvertedBase.get();
4764
4765 QualType BaseType = Base->getType();
Sam McCall3dea5272019-06-10 15:17:52 +00004766 ExprValueKind BaseKind = Base->getValueKind();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004767
4768 if (IsArrow) {
Sam McCall3dea5272019-06-10 15:17:52 +00004769 if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004770 BaseType = Ptr->getPointeeType();
Sam McCall3dea5272019-06-10 15:17:52 +00004771 BaseKind = VK_LValue;
4772 } else if (BaseType->isObjCObjectPointerType())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004773 /*Do nothing*/;
4774 else
4775 return false;
4776 }
4777
4778 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Sam McCall3dea5272019-06-10 15:17:52 +00004779 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004780 Record->getDecl(),
4781 std::move(AccessOpFixIt));
4782 } else if (const auto *TST =
4783 BaseType->getAs<TemplateSpecializationType>()) {
4784 TemplateName TN = TST->getTemplateName();
4785 if (const auto *TD =
4786 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4787 CXXRecordDecl *RD = TD->getTemplatedDecl();
Sam McCall3dea5272019-06-10 15:17:52 +00004788 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
4789 RD, std::move(AccessOpFixIt));
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004790 }
4791 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4792 if (auto *RD = ICNT->getDecl())
Sam McCall3dea5272019-06-10 15:17:52 +00004793 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
4794 RD, std::move(AccessOpFixIt));
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004795 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4796 // Objective-C property reference.
4797 AddedPropertiesSet AddedProperties;
4798
4799 if (const ObjCObjectPointerType *ObjCPtr =
4800 BaseType->getAsObjCInterfacePointerType()) {
4801 // Add property results based on our interface.
4802 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4803 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4804 /*AllowNullaryMethods=*/true, CurContext,
4805 AddedProperties, Results, IsBaseExprStatement);
4806 }
4807
4808 // Add properties from the protocols in a qualified interface.
4809 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4810 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4811 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004812 IsBaseExprStatement, /*IsClassProperty*/ false,
4813 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004814 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4815 (!IsArrow && BaseType->isObjCObjectType())) {
4816 // Objective-C instance variable access.
4817 ObjCInterfaceDecl *Class = nullptr;
4818 if (const ObjCObjectPointerType *ObjCPtr =
4819 BaseType->getAs<ObjCObjectPointerType>())
4820 Class = ObjCPtr->getInterfaceDecl();
4821 else
4822 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4823
4824 // Add all ivars from this class and its superclasses.
4825 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004826 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004827 Results.setFilter(&ResultBuilder::IsObjCIvar);
4828 LookupVisibleDecls(
4829 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4830 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4831 }
4832 }
4833
4834 // FIXME: How do we cope with isa?
4835 return true;
4836 };
4837
Douglas Gregor9291bad2009-11-18 01:29:26 +00004838 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004839
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004840 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4841 if (CodeCompleter->includeFixIts()) {
4842 const CharSourceRange OpRange =
4843 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4844 CompletionSucceded |= DoCompletion(
4845 OtherOpBase, !IsArrow,
4846 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004847 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004848
Douglas Gregor9291bad2009-11-18 01:29:26 +00004849 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004850
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004851 if (!CompletionSucceded)
4852 return;
4853
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004854 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004855 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4856 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004857}
4858
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004859void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4860 IdentifierInfo &ClassName,
4861 SourceLocation ClassNameLoc,
4862 bool IsBaseExprStatement) {
4863 IdentifierInfo *ClassNamePtr = &ClassName;
4864 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4865 if (!IFace)
4866 return;
4867 CodeCompletionContext CCContext(
4868 CodeCompletionContext::CCC_ObjCPropertyAccess);
4869 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4870 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4871 &ResultBuilder::IsMember);
4872 Results.EnterNewScope();
4873 AddedPropertiesSet AddedProperties;
4874 AddObjCProperties(CCContext, IFace, true,
4875 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4876 Results, IsBaseExprStatement,
4877 /*IsClassProperty=*/true);
4878 Results.ExitScope();
4879 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4880 Results.data(), Results.size());
4881}
4882
Faisal Vali090da2d2018-01-01 18:23:28 +00004883void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004884 if (!CodeCompleter)
4885 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004886
4887 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004888 enum CodeCompletionContext::Kind ContextKind =
4889 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004890 switch ((DeclSpec::TST)TagSpec) {
4891 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004892 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004893 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004894 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004895
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004896 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004897 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004898 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004899 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004900
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004901 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004902 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004903 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004904 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004905 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004906 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004907
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004908 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004909 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004910 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004911
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004912 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4913 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004914 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004915
4916 // First pass: look for tags.
4917 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004918 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004919 CodeCompleter->includeGlobals(),
4920 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004921
Douglas Gregor39982192010-08-15 06:18:01 +00004922 if (CodeCompleter->includeGlobals()) {
4923 // Second pass: look for nested name specifiers.
4924 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004925 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4926 CodeCompleter->includeGlobals(),
4927 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004928 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004929
Douglas Gregor0ac41382010-09-23 23:01:17 +00004930 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004931 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004932}
4933
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004934static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4935 const LangOptions &LangOpts) {
4936 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4937 Results.AddResult("const");
4938 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4939 Results.AddResult("volatile");
4940 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4941 Results.AddResult("restrict");
4942 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4943 Results.AddResult("_Atomic");
4944 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4945 Results.AddResult("__unaligned");
4946}
4947
Douglas Gregor28c78432010-08-27 17:35:51 +00004948void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004949 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004950 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004951 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004952 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004953 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004954 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004955 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004956 Results.data(), Results.size());
4957}
4958
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004959void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4960 const VirtSpecifiers *VS) {
4961 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4962 CodeCompleter->getCodeCompletionTUInfo(),
4963 CodeCompletionContext::CCC_TypeQualifiers);
4964 Results.EnterNewScope();
4965 AddTypeQualifierResults(DS, Results, LangOpts);
4966 if (LangOpts.CPlusPlus11) {
4967 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004968 if (D.getContext() == DeclaratorContext::MemberContext &&
4969 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004970 if (!VS || !VS->isFinalSpecified())
4971 Results.AddResult("final");
4972 if (!VS || !VS->isOverrideSpecified())
4973 Results.AddResult("override");
4974 }
4975 }
4976 Results.ExitScope();
4977 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4978 Results.data(), Results.size());
4979}
4980
Benjamin Kramer72dae622016-02-18 15:30:24 +00004981void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4982 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4983}
4984
Douglas Gregord328d572009-09-21 18:10:23 +00004985void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004986 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004987 return;
John McCall5939b162011-08-06 07:30:58 +00004988
Richard Smithef6c43d2018-07-26 18:41:30 +00004989 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004990 // Condition expression might be invalid, do not continue in this case.
4991 if (!Switch->getCond())
4992 return;
John McCall5939b162011-08-06 07:30:58 +00004993 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4994 if (!type->isEnumeralType()) {
4995 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004996 Data.IntegralConstantExpression = true;
4997 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004998 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004999 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005000
Douglas Gregord328d572009-09-21 18:10:23 +00005001 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005002 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00005003 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005004 if (EnumDecl *Def = Enum->getDefinition())
5005 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005006
Douglas Gregord328d572009-09-21 18:10:23 +00005007 // Determine which enumerators we have already seen in the switch statement.
5008 // FIXME: Ideally, we would also be able to look *past* the code-completion
5009 // token, in case we are code-completing in the middle of the switch and not
5010 // at the end. However, we aren't able to do so at the moment.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005011 CoveredEnumerators Enumerators;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005012 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00005013 SC = SC->getNextSwitchCase()) {
5014 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
5015 if (!Case)
5016 continue;
5017
5018 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00005019 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
5020 if (auto *Enumerator =
5021 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005022 // We look into the AST of the case statement to determine which
5023 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00005024 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005025 // values of each enumerator. However, value-based approach would not
5026 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00005027 // template are type- and value-dependent.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005028 Enumerators.Seen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005029
Douglas Gregorf2510672009-09-21 19:57:38 +00005030 // If this is a qualified-id, keep track of the nested-name-specifier
5031 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00005032 //
5033 // switch (TagD.getKind()) {
5034 // case TagDecl::TK_enum:
5035 // break;
5036 // case XXX
5037 //
Douglas Gregorf2510672009-09-21 19:57:38 +00005038 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00005039 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
5040 // TK_struct, and TK_class.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005041 Enumerators.SuggestedQualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00005042 }
5043 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005044
Douglas Gregord328d572009-09-21 18:10:23 +00005045 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005046 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005047 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005048 CodeCompletionContext::CCC_Expression);
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005049 AddEnumerators(Results, Context, Enum, CurContext, Enumerators);
Douglas Gregor285560922010-04-06 20:02:15 +00005050
Douglas Gregor21325842011-07-07 16:03:39 +00005051 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00005052 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00005053 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00005054 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5055 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00005056}
5057
Robert Wilhelm16e94b92013-08-09 18:02:13 +00005058static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005059 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005060 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005061
5062 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005063 if (!Args[I])
5064 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005065
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005066 return false;
5067}
5068
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005069typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
5070
Fangrui Song050229d2018-11-24 00:14:31 +00005071static void mergeCandidatesWithResults(
5072 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
5073 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Fangrui Song899d1392019-04-24 14:43:05 +00005074 // Sort the overload candidate set by placing the best overloads first.
5075 llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
5076 const OverloadCandidate &Y) {
5077 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
5078 CandidateSet.getKind());
5079 });
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005080
Fangrui Song899d1392019-04-24 14:43:05 +00005081 // Add the remaining viable overload candidates as code-completion results.
5082 for (OverloadCandidate &Candidate : CandidateSet) {
5083 if (Candidate.Function && Candidate.Function->isDeleted())
5084 continue;
5085 if (Candidate.Viable)
5086 Results.push_back(ResultCandidate(Candidate.Function));
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005087 }
5088}
5089
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005090/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005091/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00005092static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00005093 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005094
5095 // Given the overloads 'Candidates' for a function call matching all arguments
5096 // up to N, return the type of the Nth parameter if it is the same for all
5097 // overload candidates.
5098 QualType ParamType;
5099 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00005100 if (const auto *FType = Candidate.getFunctionType())
5101 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005102 if (N < Proto->getNumParams()) {
5103 if (ParamType.isNull())
5104 ParamType = Proto->getParamType(N);
5105 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00005106 ParamType.getNonReferenceType(),
5107 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005108 // Otherwise return a default-constructed QualType.
5109 return QualType();
5110 }
5111 }
5112
5113 return ParamType;
5114}
5115
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005116static QualType
5117ProduceSignatureHelp(Sema &SemaRef, Scope *S,
5118 MutableArrayRef<ResultCandidate> Candidates,
5119 unsigned CurrentArg, SourceLocation OpenParLoc) {
5120 if (Candidates.empty())
5121 return QualType();
5122 SemaRef.CodeCompleter->ProcessOverloadCandidates(
5123 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
5124 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005125}
5126
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005127QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
5128 ArrayRef<Expr *> Args,
5129 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00005130 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005131 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005132
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005133 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00005134 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005135 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
5136 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005137 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005138 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005139
John McCall57500772009-12-16 12:17:52 +00005140 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00005141 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00005142 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00005143
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005144 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00005145
John McCall57500772009-12-16 12:17:52 +00005146 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005147 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005148 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005149 /*PartialOverloading=*/true);
5150 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
5151 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
5152 if (UME->hasExplicitTemplateArgs()) {
5153 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
5154 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00005155 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00005156
5157 // Add the base as first argument (use a nullptr if the base is implicit).
5158 SmallVector<Expr *, 12> ArgExprs(
5159 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005160 ArgExprs.append(Args.begin(), Args.end());
5161 UnresolvedSet<8> Decls;
5162 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00005163 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005164 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005165 /*SuppressUserConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00005166 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005167 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005168 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00005169 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005170 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00005171 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005172 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005173 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00005174 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005175 !FD->getType()->getAs<FunctionProtoType>())
5176 Results.push_back(ResultCandidate(FD));
5177 else
5178 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
5179 Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005180 /*SuppressUserConversions=*/false,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005181 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005182
5183 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
5184 // If expression's type is CXXRecordDecl, it may overload the function
5185 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005186 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00005187 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00005188 DeclarationName OpName =
5189 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005190 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
5191 LookupQualifiedName(R, DC);
5192 R.suppressDiagnostics();
5193 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
5194 ArgExprs.append(Args.begin(), Args.end());
5195 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
5196 /*ExplicitArgs=*/nullptr,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005197 /*SuppressUserConversions=*/false,
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005198 /*PartialOverloading=*/true);
5199 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005200 } else {
5201 // Lastly we check whether expression's type is function pointer or
5202 // function.
5203 QualType T = NakedFn->getType();
5204 if (!T->getPointeeType().isNull())
5205 T = T->getPointeeType();
5206
5207 if (auto FP = T->getAs<FunctionProtoType>()) {
5208 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00005209 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005210 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005211 Results.push_back(ResultCandidate(FP));
5212 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005213 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005214 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005215 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005216 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005217 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005218 QualType ParamType =
5219 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
5220 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005221}
5222
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005223QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
5224 SourceLocation Loc,
5225 ArrayRef<Expr *> Args,
5226 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005227 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005228 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005229
5230 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00005231 CXXRecordDecl *RD =
5232 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005233 if (!RD)
5234 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00005235
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005236 // FIXME: Provide support for member initializers.
5237 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005238
5239 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
5240
Fangrui Song050229d2018-11-24 00:14:31 +00005241 for (NamedDecl *C : LookupConstructors(RD)) {
5242 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
5243 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
5244 CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005245 /*SuppressUserConversions=*/false,
Richard Smith76b90272019-05-09 03:59:21 +00005246 /*PartialOverloading=*/true,
5247 /*AllowExplicit*/ true);
Fangrui Song050229d2018-11-24 00:14:31 +00005248 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
5249 AddTemplateOverloadCandidate(
5250 FTD, DeclAccessPair::make(FTD, C->getAccess()),
5251 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005252 /*SuppressUserConversions=*/false,
Hans Wennborgd2b9fc82019-05-06 09:51:10 +00005253 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005254 }
5255 }
5256
5257 SmallVector<ResultCandidate, 8> Results;
5258 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005259 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00005260}
5261
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00005262QualType Sema::ProduceCtorInitMemberSignatureHelp(
5263 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
5264 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
5265 if (!CodeCompleter)
5266 return QualType();
5267
5268 CXXConstructorDecl *Constructor =
5269 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
5270 if (!Constructor)
5271 return QualType();
5272 // FIXME: Add support for Base class constructors as well.
5273 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
5274 Constructor->getParent(), SS, TemplateTypeTy, II))
5275 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
5276 MemberDecl->getLocation(), ArgExprs,
5277 OpenParLoc);
5278 return QualType();
5279}
5280
John McCall48871652010-08-21 09:40:31 +00005281void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
5282 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005283 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005284 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005285 return;
5286 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005287
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005288 CodeCompleteExpressionData Data;
5289 Data.PreferredType = VD->getType();
5290 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5291 Data.IgnoreDecls.push_back(VD);
5292
5293 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005294}
5295
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005296void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005297 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005298 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005299 mapCodeCompletionContext(*this, PCC_Statement));
5300 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5301 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005302
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005303 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5304 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005305 CodeCompleter->includeGlobals(),
5306 CodeCompleter->loadExternal());
5307
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005308 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005309
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005310 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005311 CodeCompletionBuilder Builder(Results.getAllocator(),
5312 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005313 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005314 if (Results.includeCodePatterns()) {
5315 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5316 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5317 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5318 Builder.AddPlaceholderChunk("statements");
5319 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5320 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5321 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005322 Results.AddResult(Builder.TakeString());
5323
5324 // "else if" block
Ilya Biryukov30977fc2019-06-04 09:26:08 +00005325 Builder.AddTypedTextChunk("else if");
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005326 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5327 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005328 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005329 Builder.AddPlaceholderChunk("condition");
5330 else
5331 Builder.AddPlaceholderChunk("expression");
5332 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005333 if (Results.includeCodePatterns()) {
5334 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5335 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5336 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5337 Builder.AddPlaceholderChunk("statements");
5338 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5339 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5340 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005341 Results.AddResult(Builder.TakeString());
5342
5343 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005344
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005345 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005346 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005347
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005348 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005349 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005350
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005351 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005352 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005353}
5354
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005355void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005356 bool EnteringContext,
5357 bool IsUsingDeclaration, QualType BaseType,
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005358 QualType PreferredType) {
Eric Liu06d34022017-12-12 11:35:46 +00005359 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005360 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005361
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005362 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType);
5363 CC.setIsUsingDeclaration(IsUsingDeclaration);
5364 CC.setCXXScopeSpecifier(SS);
5365
Eric Liu06d34022017-12-12 11:35:46 +00005366 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5367 // "a::b::" is not corresponding to any context/namespace in the AST), since
5368 // it can be useful for global code completion which have information about
5369 // contexts/symbols that are not in the AST.
5370 if (SS.isInvalid()) {
Eric Liu206740e2019-02-21 11:22:58 +00005371 // As SS is invalid, we try to collect accessible contexts from the current
5372 // scope with a dummy lookup so that the completion consumer can try to
5373 // guess what the specified scope is.
5374 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5375 CodeCompleter->getCodeCompletionTUInfo(), CC);
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005376 if (!PreferredType.isNull())
5377 DummyResults.setPreferredType(PreferredType);
Eric Liu206740e2019-02-21 11:22:58 +00005378 if (S->getEntity()) {
5379 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5380 BaseType);
5381 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5382 /*IncludeGlobalScope=*/false,
5383 /*LoadExternal=*/false);
5384 }
5385 HandleCodeCompleteResults(this, CodeCompleter,
5386 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005387 return;
5388 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005389 // Always pretend to enter a context to ensure that a dependent type
5390 // resolves to a dependent record.
5391 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005392 if (!Ctx)
5393 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005394
5395 // Try to instantiate any non-dependent declaration contexts before
5396 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005397 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005398 return;
5399
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005400 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5401 CodeCompleter->getCodeCompletionTUInfo(), CC);
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005402 if (!PreferredType.isNull())
5403 Results.setPreferredType(PreferredType);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005404 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005405
Douglas Gregor3545ff42009-09-21 16:56:56 +00005406 // The "template" keyword can follow "::" in the grammar, but only
5407 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005408 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005409 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005410 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005411
5412 // Add calls to overridden virtual functions, if there are any.
5413 //
5414 // FIXME: This isn't wonderful, because we don't know whether we're actually
5415 // in a context that permits expressions. This is a general issue with
5416 // qualified-id completions.
5417 if (!EnteringContext)
5418 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005419 Results.ExitScope();
5420
Eric Liufead6ae2017-12-13 10:26:49 +00005421 if (CodeCompleter->includeNamespaceLevelDecls() ||
5422 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005423 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005424 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5425 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005426 /*IncludeDependentBases=*/true,
5427 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005428 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005429
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005430 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5431 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005432}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005433
5434void Sema::CodeCompleteUsing(Scope *S) {
5435 if (!CodeCompleter)
5436 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005437
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005438 // This can be both a using alias or using declaration, in the former we
5439 // expect a new name and a symbol in the latter case.
5440 CodeCompletionContext Context(CodeCompletionContext::CCC_SymbolOrNewName);
5441 Context.setIsUsingDeclaration(true);
5442
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005443 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005444 CodeCompleter->getCodeCompletionTUInfo(), Context,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005445 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005446 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005447
Douglas Gregor3545ff42009-09-21 16:56:56 +00005448 // If we aren't in class scope, we could see the "namespace" keyword.
5449 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005450 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005451
5452 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005453 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005454 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005455 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005456 CodeCompleter->includeGlobals(),
5457 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005458 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005459
5460 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5461 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005462}
5463
5464void Sema::CodeCompleteUsingDirective(Scope *S) {
5465 if (!CodeCompleter)
5466 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005467
Douglas Gregor3545ff42009-09-21 16:56:56 +00005468 // After "using namespace", we expect to see a namespace name or namespace
5469 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005470 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005471 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005472 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005473 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005474 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005475 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005476 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005477 CodeCompleter->includeGlobals(),
5478 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005479 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005480 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5481 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005482}
5483
Fangrui Song050229d2018-11-24 00:14:31 +00005484void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005485 if (!CodeCompleter)
5486 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005487
Ted Kremenekc37877d2013-10-08 17:08:03 +00005488 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005489 if (!S->getParent())
5490 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005491
Fangrui Song050229d2018-11-24 00:14:31 +00005492 bool SuppressedGlobalResults =
5493 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005494
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005495 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005496 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005497 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005498 ? CodeCompletionContext::CCC_Namespace
5499 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005500 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005501
Douglas Gregor0ac41382010-09-23 23:01:17 +00005502 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005503 // We only want to see those namespaces that have already been defined
5504 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005505 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005506 // definition of each namespace.
5507 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005508 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005509 NS(Ctx->decls_begin()),
5510 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005511 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005512 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005513
5514 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005515 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005516 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005517 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005518 NS = OrigToLatest.begin(),
5519 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005520 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005521 Results.AddResult(
5522 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5523 nullptr),
5524 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005525 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005526 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005527
Fangrui Song050229d2018-11-24 00:14:31 +00005528 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5529 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005530}
5531
Fangrui Song050229d2018-11-24 00:14:31 +00005532void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005533 if (!CodeCompleter)
5534 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005535
Douglas Gregor3545ff42009-09-21 16:56:56 +00005536 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005537 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005538 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005539 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005540 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005541 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005542 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005543 CodeCompleter->includeGlobals(),
5544 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005545 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5546 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005547}
5548
Douglas Gregorc811ede2009-09-18 20:05:18 +00005549void Sema::CodeCompleteOperatorName(Scope *S) {
5550 if (!CodeCompleter)
5551 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005552
John McCall276321a2010-08-25 06:19:51 +00005553 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005554 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005555 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005556 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005557 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005558 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005559
Richard Smith7fa2b742019-06-14 20:01:51 +00005560 // Add the names of overloadable operators. Note that OO_Conditional is not
5561 // actually overloadable.
Fangrui Song050229d2018-11-24 00:14:31 +00005562#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
Richard Smith7fa2b742019-06-14 20:01:51 +00005563 if (OO_##Name != OO_Conditional) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005564 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005565#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005566
Douglas Gregor3545ff42009-09-21 16:56:56 +00005567 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005568 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005569 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005570 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005571 CodeCompleter->includeGlobals(),
5572 CodeCompleter->loadExternal());
5573
Douglas Gregor3545ff42009-09-21 16:56:56 +00005574 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005575 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005576 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005577
5578 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5579 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005580}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005581
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005582void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005583 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005584 if (!ConstructorD)
5585 return;
5586
5587 AdjustDeclIfTemplate(ConstructorD);
5588
Fangrui Song050229d2018-11-24 00:14:31 +00005589 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005590 if (!Constructor)
5591 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005592
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005593 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005594 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005595 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005596 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005597
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005598 // Fill in any already-initialized fields or base classes.
5599 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5600 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005601 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005602 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005603 InitializedBases.insert(Context.getCanonicalType(
5604 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005605 else
Fangrui Song050229d2018-11-24 00:14:31 +00005606 InitializedFields.insert(
5607 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005608 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005609
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005610 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005611 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005612 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005613 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005614
5615 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5616 CodeCompletionBuilder Builder(Results.getAllocator(),
5617 Results.getCodeCompletionTUInfo());
5618 Builder.AddTypedTextChunk(Name);
5619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005620 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005621 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005622 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005623 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5624 Builder);
5625 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5626 return Builder.TakeString();
5627 };
5628 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5629 const NamedDecl *ND) {
5630 CodeCompletionBuilder Builder(Results.getAllocator(),
5631 Results.getCodeCompletionTUInfo());
5632 Builder.AddTypedTextChunk(Name);
5633 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5634 Builder.AddPlaceholderChunk(Type);
5635 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5636 if (ND) {
5637 auto CCR = CodeCompletionResult(
5638 Builder.TakeString(), ND,
5639 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5640 if (isa<FieldDecl>(ND))
5641 CCR.CursorKind = CXCursor_MemberRef;
5642 return Results.AddResult(CCR);
5643 }
5644 return Results.AddResult(CodeCompletionResult(
5645 Builder.TakeString(),
5646 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5647 };
5648 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5649 const char *Name, const FieldDecl *FD) {
5650 if (!RD)
5651 return AddDefaultCtorInit(Name,
5652 FD ? Results.getAllocator().CopyString(
5653 FD->getType().getAsString(Policy))
5654 : Name,
5655 FD);
5656 auto Ctors = getConstructors(Context, RD);
5657 if (Ctors.begin() == Ctors.end())
5658 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005659 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005660 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5661 CCR.CursorKind = getCursorKindForDecl(Ctor);
5662 Results.AddResult(CCR);
5663 }
5664 };
5665 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5666 const char *BaseName =
5667 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5668 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5669 AddCtorsWithName(
5670 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5671 BaseName, nullptr);
5672 };
5673 auto AddField = [&](const FieldDecl *FD) {
5674 const char *FieldName =
5675 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5676 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5677 AddCtorsWithName(
5678 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5679 FieldName, FD);
5680 };
5681
Aaron Ballman574705e2014-03-13 15:41:46 +00005682 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005683 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5684 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005685 SawLastInitializer =
5686 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5687 Context.hasSameUnqualifiedType(
5688 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005689 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005690 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005691
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005692 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005693 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005694 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005695
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005696 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005697 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005698 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5699 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005700 SawLastInitializer =
5701 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5702 Context.hasSameUnqualifiedType(
5703 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005704 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005705 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005706
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005707 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005708 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005709 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005710
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005711 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005712 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005713 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5714 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005715 SawLastInitializer = !Initializers.empty() &&
5716 Initializers.back()->isAnyMemberInitializer() &&
5717 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005718 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005719 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005720
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005721 if (!Field->getDeclName())
5722 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005723
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005724 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005725 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005726 }
5727 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005728
Douglas Gregor0ac41382010-09-23 23:01:17 +00005729 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005730 Results.data(), Results.size());
5731}
5732
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005733/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005734static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005735 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005736 if (!DC)
5737 return false;
5738
5739 return DC->isFileContext();
5740}
5741
5742void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5743 bool AfterAmpersand) {
5744 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005745 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005746 CodeCompletionContext::CCC_Other);
5747 Results.EnterNewScope();
5748
5749 // Note what has already been captured.
5750 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5751 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005752 for (const auto &C : Intro.Captures) {
5753 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005754 IncludedThis = true;
5755 continue;
5756 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005757
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005758 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005759 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005760
Douglas Gregord8c61782012-02-15 15:34:24 +00005761 // Look for other capturable variables.
5762 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005763 for (const auto *D : S->decls()) {
5764 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005765 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005766 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005767
David Blaikie82e95a32014-11-19 07:49:47 +00005768 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005769 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005770 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005771 }
5772 }
5773
5774 // Add 'this', if it would be valid.
5775 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5776 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005777
Douglas Gregord8c61782012-02-15 15:34:24 +00005778 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005779
Douglas Gregord8c61782012-02-15 15:34:24 +00005780 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5781 Results.data(), Results.size());
5782}
5783
James Dennett596e4752012-06-14 03:11:41 +00005784/// Macro that optionally prepends an "@" to the string literal passed in via
5785/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005786#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005787
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005788static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005789 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005790 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005791 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005792 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005793
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005794 CodeCompletionBuilder Builder(Results.getAllocator(),
5795 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005796 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005797 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005798 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5800 Builder.AddPlaceholderChunk("property");
5801 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005802
Douglas Gregorf1934162010-01-13 21:24:21 +00005803 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005804 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005805 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5806 Builder.AddPlaceholderChunk("property");
5807 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005808 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005809}
5810
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005811static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005812 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005813 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005814
Douglas Gregorf1934162010-01-13 21:24:21 +00005815 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005816 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005817
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005818 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005819 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005820 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005821
Douglas Gregorf1934162010-01-13 21:24:21 +00005822 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005823 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005824
Douglas Gregorf1934162010-01-13 21:24:21 +00005825 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005826 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005827 }
5828}
5829
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005830static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005831 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005832 CodeCompletionBuilder Builder(Results.getAllocator(),
5833 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005834
Douglas Gregorf1934162010-01-13 21:24:21 +00005835 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005836 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005837 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5838 Builder.AddPlaceholderChunk("name");
5839 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005840
Douglas Gregorf4c33342010-05-28 00:22:41 +00005841 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005842 // @interface name
5843 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005844 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005845 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005846 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5847 Builder.AddPlaceholderChunk("class");
5848 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005849
Douglas Gregorf4c33342010-05-28 00:22:41 +00005850 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005851 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005852 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5853 Builder.AddPlaceholderChunk("protocol");
5854 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005855
Douglas Gregorf4c33342010-05-28 00:22:41 +00005856 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005857 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5859 Builder.AddPlaceholderChunk("class");
5860 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005861 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005862
Douglas Gregorf1934162010-01-13 21:24:21 +00005863 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005864 Builder.AddTypedTextChunk(
5865 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005866 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5867 Builder.AddPlaceholderChunk("alias");
5868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5869 Builder.AddPlaceholderChunk("class");
5870 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005871
5872 if (Results.getSema().getLangOpts().Modules) {
5873 // @import name
5874 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5875 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5876 Builder.AddPlaceholderChunk("module");
5877 Results.AddResult(Result(Builder.TakeString()));
5878 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005879}
5880
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005881void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005882 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005883 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005884 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005885 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005886 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005887 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005888 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005889 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005890 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005891 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005892 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005893 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5894 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005895}
5896
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005897static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005898 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005899 CodeCompletionBuilder Builder(Results.getAllocator(),
5900 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005901
5902 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005903 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005904 if (Results.getSema().getLangOpts().CPlusPlus ||
5905 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005906 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005907 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005908 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005909 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5910 Builder.AddPlaceholderChunk("type-name");
5911 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5912 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005913
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005914 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005915 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005916 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005917 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5918 Builder.AddPlaceholderChunk("protocol-name");
5919 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5920 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005921
5922 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005923 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005924 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005925 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5926 Builder.AddPlaceholderChunk("selector");
5927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5928 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005929
5930 // @"string"
5931 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005932 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005933 Builder.AddPlaceholderChunk("string");
5934 Builder.AddTextChunk("\"");
5935 Results.AddResult(Result(Builder.TakeString()));
5936
Douglas Gregor951de302012-07-17 23:24:47 +00005937 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005938 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005939 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005940 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005941 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5942 Results.AddResult(Result(Builder.TakeString()));
5943
Douglas Gregor951de302012-07-17 23:24:47 +00005944 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005945 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005946 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005947 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005948 Builder.AddChunk(CodeCompletionString::CK_Colon);
5949 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5950 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005951 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5952 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005953
Douglas Gregor951de302012-07-17 23:24:47 +00005954 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005955 Builder.AddResultTypeChunk("id");
5956 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005957 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005958 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5959 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005960}
5961
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005962static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005963 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005964 CodeCompletionBuilder Builder(Results.getAllocator(),
5965 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005966
Douglas Gregorf4c33342010-05-28 00:22:41 +00005967 if (Results.includeCodePatterns()) {
5968 // @try { statements } @catch ( declaration ) { statements } @finally
5969 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005970 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005971 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5972 Builder.AddPlaceholderChunk("statements");
5973 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5974 Builder.AddTextChunk("@catch");
5975 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5976 Builder.AddPlaceholderChunk("parameter");
5977 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5978 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5979 Builder.AddPlaceholderChunk("statements");
5980 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5981 Builder.AddTextChunk("@finally");
5982 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5983 Builder.AddPlaceholderChunk("statements");
5984 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5985 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005986 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005987
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005988 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005989 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005990 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5991 Builder.AddPlaceholderChunk("expression");
5992 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005993
Douglas Gregorf4c33342010-05-28 00:22:41 +00005994 if (Results.includeCodePatterns()) {
5995 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005996 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005997 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5998 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5999 Builder.AddPlaceholderChunk("expression");
6000 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6001 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6002 Builder.AddPlaceholderChunk("statements");
6003 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
6004 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00006005 }
Douglas Gregorf1934162010-01-13 21:24:21 +00006006}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006007
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006008static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00006009 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00006010 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006011 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
6012 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
6013 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00006014 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00006015 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00006016}
6017
6018void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006019 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006020 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006021 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00006022 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00006023 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00006024 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006025 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6026 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00006027}
6028
6029void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006030 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006031 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006032 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00006033 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006034 AddObjCStatementResults(Results, false);
6035 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006036 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006037 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6038 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006039}
6040
6041void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006042 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006043 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006044 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006045 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006046 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006047 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006048 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6049 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006050}
6051
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006052/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00006053/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00006054static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00006055 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00006056 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00006057 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006058
Bill Wendling44426052012-12-20 19:22:21 +00006059 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006060
Douglas Gregore6078da2009-11-19 00:14:45 +00006061 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00006062 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
6063 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00006064 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006065
Jordan Rose53cb2f32012-08-20 20:01:13 +00006066 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00006067 unsigned AssignCopyRetMask =
6068 Attributes &
6069 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
6070 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
6071 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
6072 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00006073 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00006074 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00006075 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00006076 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
6077 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00006078 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006079
Douglas Gregore6078da2009-11-19 00:14:45 +00006080 return false;
6081}
6082
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006083void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00006084 if (!CodeCompleter)
6085 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006086
Bill Wendling44426052012-12-20 19:22:21 +00006087 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006088
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006089 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006090 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006091 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00006092 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00006093 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00006094 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00006095 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00006096 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00006097 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00006098 ObjCDeclSpec::DQ_PR_unsafe_unretained))
6099 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00006100 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00006101 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00006102 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00006103 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00006104 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00006105 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00006106 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00006107 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00006108 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00006109 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00006110 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00006111 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00006112
6113 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00006114 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00006115 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00006116 Results.AddResult(CodeCompletionResult("weak"));
6117
Bill Wendling44426052012-12-20 19:22:21 +00006118 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006119 CodeCompletionBuilder Setter(Results.getAllocator(),
6120 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006121 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006122 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006123 Setter.AddPlaceholderChunk("method");
6124 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006125 }
Bill Wendling44426052012-12-20 19:22:21 +00006126 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006127 CodeCompletionBuilder Getter(Results.getAllocator(),
6128 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006129 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006130 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006131 Getter.AddPlaceholderChunk("method");
6132 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006133 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006134 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
6135 Results.AddResult(CodeCompletionResult("nonnull"));
6136 Results.AddResult(CodeCompletionResult("nullable"));
6137 Results.AddResult(CodeCompletionResult("null_unspecified"));
6138 Results.AddResult(CodeCompletionResult("null_resettable"));
6139 }
Steve Naroff936354c2009-10-08 21:55:05 +00006140 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006141 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6142 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00006143}
Steve Naroffeae65032009-11-07 02:08:14 +00006144
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006145/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00006146/// via code completion.
6147enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00006148 MK_Any, ///< Any kind of method, provided it means other specified criteria.
6149 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00006150 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006151};
6152
Fangrui Song050229d2018-11-24 00:14:31 +00006153static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006154 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006155 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006156 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006157 if (NumSelIdents > Sel.getNumArgs())
6158 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006159
Douglas Gregor67c692c2010-08-26 15:07:07 +00006160 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00006161 case MK_Any:
6162 break;
6163 case MK_ZeroArgSelector:
6164 return Sel.isUnarySelector();
6165 case MK_OneArgSelector:
6166 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006167 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006168
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006169 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
6170 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006171
Douglas Gregor67c692c2010-08-26 15:07:07 +00006172 for (unsigned I = 0; I != NumSelIdents; ++I)
6173 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
6174 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006175
Douglas Gregor67c692c2010-08-26 15:07:07 +00006176 return true;
6177}
6178
Douglas Gregorc8537c52009-11-19 07:41:15 +00006179static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
6180 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006181 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006182 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006183 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006184 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006185}
Douglas Gregor1154e272010-09-16 16:06:31 +00006186
Fangrui Song050229d2018-11-24 00:14:31 +00006187/// A set of selectors, which is used to avoid introducing multiple
6188/// completions with the same selector into the result set.
6189typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00006190
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006191/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006192/// container to the set of results.
6193///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006194/// The container will be a class, protocol, category, or implementation of
6195/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006196/// the superclasses of classes along with their categories, protocols, and
6197/// implementations.
6198///
6199/// \param Container the container in which we'll look to find methods.
6200///
James Dennett596e4752012-06-14 03:11:41 +00006201/// \param WantInstanceMethods Whether to add instance methods (only); if
6202/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006203///
6204/// \param CurContext the context in which we're performing the lookup that
6205/// finds methods.
6206///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006207/// \param AllowSameLength Whether we allow a method to be added to the list
6208/// when it has the same number of parameters as we have selector identifiers.
6209///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006210/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006211static void AddObjCMethods(ObjCContainerDecl *Container,
6212 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006213 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006214 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006215 VisitedSelectorSet &Selectors, bool AllowSameLength,
6216 ResultBuilder &Results, bool InOriginalClass = true,
6217 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00006218 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006219 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00006220 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00006221 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00006222 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00006223 // The instance methods on the root class can be messaged via the
6224 // metaclass.
6225 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00006226 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006227 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00006228 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006229 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00006230 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00006231
David Blaikie82e95a32014-11-19 07:49:47 +00006232 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006233 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006234
6235 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006236 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00006237 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00006238 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00006239 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00006240 Results.MaybeAddResult(R, CurContext);
6241 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006242 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006243
Douglas Gregorf37c9492010-09-16 15:34:59 +00006244 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006245 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00006246 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006247 const ObjCList<ObjCProtocolDecl> &Protocols =
6248 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006249 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006250 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006251 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006252 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6253 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00006254 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00006255 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006256
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006257 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006258 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006259
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006260 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006261 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006262 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6263 Selectors, AllowSameLength, Results, false, IsRootClass);
6264
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006265 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00006266 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006267 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006268 CurContext, Selectors, AllowSameLength, Results,
6269 InOriginalClass, IsRootClass);
6270
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006271 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00006272 const ObjCList<ObjCProtocolDecl> &Protocols =
6273 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006274 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6275 E = Protocols.end();
6276 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006277 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6278 Selectors, AllowSameLength, Results, false, IsRootClass);
6279
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006280 // Add methods in category implementations.
6281 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006282 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6283 Selectors, AllowSameLength, Results, InOriginalClass,
6284 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006285 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006286
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006287 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006288 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006289 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006290 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6291 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6292 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006293
6294 // Add methods in our implementation, if any.
6295 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006296 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6297 Selectors, AllowSameLength, Results, InOriginalClass,
6298 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006299}
6300
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006301void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006302 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006303 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006304 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006305 if (ObjCCategoryDecl *Category =
6306 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006307 Class = Category->getClassInterface();
6308
6309 if (!Class)
6310 return;
6311 }
6312
6313 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006314 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006315 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006316 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006317 Results.EnterNewScope();
6318
Douglas Gregor1154e272010-09-16 16:06:31 +00006319 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006320 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006321 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006322 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006323 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6324 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006325}
6326
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006327void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006328 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006329 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006330 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006331 if (ObjCCategoryDecl *Category =
6332 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006333 Class = Category->getClassInterface();
6334
6335 if (!Class)
6336 return;
6337 }
6338
6339 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006340 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006341 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006342 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006343 Results.EnterNewScope();
6344
Douglas Gregor1154e272010-09-16 16:06:31 +00006345 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006346 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6347 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006348
6349 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006350 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6351 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006352}
6353
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006354void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6355 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006356 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006357 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006358 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006359 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006360
Douglas Gregor99fa2642010-08-24 01:06:58 +00006361 // Add context-sensitive, Objective-C parameter-passing keywords.
6362 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006363 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006364 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6365 Results.AddResult("in");
6366 Results.AddResult("inout");
6367 AddedInOut = true;
6368 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006369 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006370 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6371 Results.AddResult("out");
6372 if (!AddedInOut)
6373 Results.AddResult("inout");
6374 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006375 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006376 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6377 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006378 Results.AddResult("bycopy");
6379 Results.AddResult("byref");
6380 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006381 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006382 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6383 Results.AddResult("nonnull");
6384 Results.AddResult("nullable");
6385 Results.AddResult("null_unspecified");
6386 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006387
6388 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006389 // identifier IBAction refers to a macro, provide a completion item for
6390 // an action, e.g.,
6391 // IBAction)<#selector#>:(id)sender
6392 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006393 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006394 CodeCompletionBuilder Builder(Results.getAllocator(),
6395 Results.getCodeCompletionTUInfo(),
6396 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006397 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006398 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006399 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006400 Builder.AddChunk(CodeCompletionString::CK_Colon);
6401 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006402 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006403 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006404 Builder.AddTextChunk("sender");
6405 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6406 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006407
6408 // If we're completing the return type, provide 'instancetype'.
6409 if (!IsParameter) {
6410 Results.AddResult(CodeCompletionResult("instancetype"));
6411 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006412
Douglas Gregor99fa2642010-08-24 01:06:58 +00006413 // Add various builtin type names and specifiers.
6414 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6415 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006416
Douglas Gregor99fa2642010-08-24 01:06:58 +00006417 // Add the various type names
6418 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6419 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6420 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006421 CodeCompleter->includeGlobals(),
6422 CodeCompleter->loadExternal());
6423
Douglas Gregor99fa2642010-08-24 01:06:58 +00006424 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006425 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006426
Eric Liuf5ba09f2018-07-04 10:01:18 +00006427 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006428 Results.data(), Results.size());
6429}
6430
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006431/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006432/// that it has some more-specific class type based on knowledge of
6433/// common uses of Objective-C. This routine returns that class type,
6434/// or NULL if no better result could be determined.
6435static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006436 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006437 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006438 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006439
6440 Selector Sel = Msg->getSelector();
6441 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006442 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006443
6444 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6445 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006446 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006447
6448 ObjCMethodDecl *Method = Msg->getMethodDecl();
6449 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006450 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006451
6452 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006453 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006454 switch (Msg->getReceiverKind()) {
6455 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006456 if (const ObjCObjectType *ObjType =
6457 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006458 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006459 break;
6460
6461 case ObjCMessageExpr::Instance: {
6462 QualType T = Msg->getInstanceReceiver()->getType();
6463 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6464 IFace = Ptr->getInterfaceDecl();
6465 break;
6466 }
6467
6468 case ObjCMessageExpr::SuperInstance:
6469 case ObjCMessageExpr::SuperClass:
6470 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006471 }
6472
6473 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006474 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006475
6476 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6477 if (Method->isInstanceMethod())
6478 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006479 .Case("retain", IFace)
6480 .Case("strong", IFace)
6481 .Case("autorelease", IFace)
6482 .Case("copy", IFace)
6483 .Case("copyWithZone", IFace)
6484 .Case("mutableCopy", IFace)
6485 .Case("mutableCopyWithZone", IFace)
6486 .Case("awakeFromCoder", IFace)
6487 .Case("replacementObjectFromCoder", IFace)
6488 .Case("class", IFace)
6489 .Case("classForCoder", IFace)
6490 .Case("superclass", Super)
6491 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006492
6493 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006494 .Case("new", IFace)
6495 .Case("alloc", IFace)
6496 .Case("allocWithZone", IFace)
6497 .Case("class", IFace)
6498 .Case("superclass", Super)
6499 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006500}
6501
Douglas Gregor6fc04132010-08-27 15:10:57 +00006502// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006503// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006504// function.
6505///
6506/// \param S The semantic analysis object.
6507///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006508/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006509/// the "super" keyword. Otherwise, we just need to provide the arguments.
6510///
6511/// \param SelIdents The identifiers in the selector that have already been
6512/// provided as arguments for a send to "super".
6513///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006514/// \param Results The set of results to augment.
6515///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006516/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006517/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006518static ObjCMethodDecl *
6519AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6520 ArrayRef<IdentifierInfo *> SelIdents,
6521 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006522 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6523 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006524 return nullptr;
6525
Douglas Gregor6fc04132010-08-27 15:10:57 +00006526 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6527 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006528 return nullptr;
6529
Douglas Gregor6fc04132010-08-27 15:10:57 +00006530 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006531 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006532 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6533 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006534 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006535 CurMethod->isInstanceMethod());
6536
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006537 // Check in categories or class extensions.
6538 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006539 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006540 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006541 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006542 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006543 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006544 }
6545 }
6546
Douglas Gregor6fc04132010-08-27 15:10:57 +00006547 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006548 return nullptr;
6549
Douglas Gregor6fc04132010-08-27 15:10:57 +00006550 // Check whether the superclass method has the same signature.
6551 if (CurMethod->param_size() != SuperMethod->param_size() ||
6552 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006553 return nullptr;
6554
Douglas Gregor6fc04132010-08-27 15:10:57 +00006555 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006556 CurPEnd = CurMethod->param_end(),
6557 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006558 CurP != CurPEnd; ++CurP, ++SuperP) {
6559 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006560 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006561 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006562 return nullptr;
6563
Douglas Gregor6fc04132010-08-27 15:10:57 +00006564 // Make sure we have a parameter name to forward!
6565 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006566 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006567 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006568
Douglas Gregor6fc04132010-08-27 15:10:57 +00006569 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006570 CodeCompletionBuilder Builder(Results.getAllocator(),
6571 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006572
Douglas Gregor6fc04132010-08-27 15:10:57 +00006573 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006574 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006575 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006576
6577 // If we need the "super" keyword, add it (plus some spacing).
6578 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006579 Builder.AddTypedTextChunk("super");
6580 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006581 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006582
Douglas Gregor6fc04132010-08-27 15:10:57 +00006583 Selector Sel = CurMethod->getSelector();
6584 if (Sel.isUnarySelector()) {
6585 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006586 Builder.AddTextChunk(
6587 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006588 else
Fangrui Song050229d2018-11-24 00:14:31 +00006589 Builder.AddTypedTextChunk(
6590 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006591 } else {
6592 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6593 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006594 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006595 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006596
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006597 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006598 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006599 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006600 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006601 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006602 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006603 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006604 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006605 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006606 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006607 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006608 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006609 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006610 }
6611 }
6612 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006613
Douglas Gregor78254c82012-03-27 23:34:16 +00006614 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6615 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006616 return SuperMethod;
6617}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006618
Douglas Gregora817a192010-05-27 23:06:34 +00006619void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006620 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006621 ResultBuilder Results(
6622 *this, CodeCompleter->getAllocator(),
6623 CodeCompleter->getCodeCompletionTUInfo(),
6624 CodeCompletionContext::CCC_ObjCMessageReceiver,
6625 getLangOpts().CPlusPlus11
6626 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6627 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006628
Douglas Gregora817a192010-05-27 23:06:34 +00006629 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6630 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006631 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006632 CodeCompleter->includeGlobals(),
6633 CodeCompleter->loadExternal());
6634
Douglas Gregora817a192010-05-27 23:06:34 +00006635 // If we are in an Objective-C method inside a class that has a superclass,
6636 // add "super" as an option.
6637 if (ObjCMethodDecl *Method = getCurMethodDecl())
6638 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006639 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006640 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006641
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006642 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006643 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006644
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006645 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006646 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006647
Douglas Gregora817a192010-05-27 23:06:34 +00006648 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006649
Douglas Gregora817a192010-05-27 23:06:34 +00006650 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006651 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006652 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006653 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006654}
6655
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006656void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006657 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006658 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006659 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006660 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6661 // Figure out which interface we're in.
6662 CDecl = CurMethod->getClassInterface();
6663 if (!CDecl)
6664 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006665
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006666 // Find the superclass of this class.
6667 CDecl = CDecl->getSuperClass();
6668 if (!CDecl)
6669 return;
6670
6671 if (CurMethod->isInstanceMethod()) {
6672 // We are inside an instance method, which means that the message
6673 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006674 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006675 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006676 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006677 }
6678
6679 // Fall through to send to the superclass in CDecl.
6680 } else {
6681 // "super" may be the name of a type or variable. Figure out which
6682 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006683 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006684 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006685 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6686 // "super" names an interface. Use it.
6687 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006688 if (const ObjCObjectType *Iface =
6689 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006690 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006691 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6692 // "super" names an unresolved type; we can't be more specific.
6693 } else {
6694 // Assume that "super" names some kind of value and parse that way.
6695 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006696 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006697 UnqualifiedId id;
6698 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006699 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6700 /*HasTrailingLParen=*/false,
6701 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006702 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006703 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006704 }
6705
6706 // Fall through
6707 }
6708
John McCallba7bf592010-08-24 05:47:05 +00006709 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006710 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006711 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006712 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006713 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006714 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006715}
6716
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006717/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006718/// send, determine the preferred type (if any) for that argument expression.
6719static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6720 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006721 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006722 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006723
Douglas Gregor74661272010-09-21 00:03:25 +00006724 QualType PreferredType;
6725 unsigned BestPriority = CCP_Unlikely * 2;
6726 Result *ResultsData = Results.data();
6727 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6728 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006729 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006730 isa<ObjCMethodDecl>(R.Declaration)) {
6731 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006732 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006733 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006734 QualType MyPreferredType =
6735 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006736 if (R.Priority < BestPriority || PreferredType.isNull()) {
6737 BestPriority = R.Priority;
6738 PreferredType = MyPreferredType;
6739 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6740 MyPreferredType)) {
6741 PreferredType = QualType();
6742 }
6743 }
6744 }
6745 }
6746 }
6747
6748 return PreferredType;
6749}
6750
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006751static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006752 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006753 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006754 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006755 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006756 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006757 ObjCInterfaceDecl *CDecl = nullptr;
6758
Douglas Gregor8ce33212009-11-17 17:59:40 +00006759 // If the given name refers to an interface type, retrieve the
6760 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006761 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006762 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006763 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006764 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6765 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006766 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006767
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006768 // Add all of the factory methods in this Objective-C class, its protocols,
6769 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006770 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006771
6772 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006773 // completion.
6774 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006775 if (ObjCMethodDecl *SuperMethod =
6776 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006777 Results.Ignore(SuperMethod);
6778 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006779
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006780 // If we're inside an Objective-C method definition, prefer its selector to
6781 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006782 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006783 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006784
Douglas Gregor1154e272010-09-16 16:06:31 +00006785 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006786 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006787 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6788 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006789 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006790 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006791
Douglas Gregord720daf2010-04-06 17:30:22 +00006792 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006793 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006794 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006795 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006796 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006797 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006798 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006799 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006800 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006801
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006802 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006803 }
6804 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006805
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006806 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006807 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006808 M != MEnd; ++M) {
6809 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006810 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006811 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006812 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006813
Nico Weber2e0c8f72014-12-27 03:58:08 +00006814 Result R(MethList->getMethod(),
6815 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006816 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006817 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006818 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006819 }
6820 }
6821 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006822
6823 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006824}
Douglas Gregor6285f752010-04-06 16:40:00 +00006825
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006826void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006827 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006828 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006829 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006830
Douglas Gregor63745d52011-07-21 01:05:26 +00006831 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006832
Fangrui Song050229d2018-11-24 00:14:31 +00006833 ResultBuilder Results(
6834 *this, CodeCompleter->getAllocator(),
6835 CodeCompleter->getCodeCompletionTUInfo(),
6836 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6837 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006838
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006839 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006840 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006841
6842 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006843 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006844 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006845 // code-complete the expression using the corresponding parameter type as
6846 // our preferred type, improving completion results.
6847 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006848 QualType PreferredType =
6849 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006850 if (PreferredType.isNull())
6851 CodeCompleteOrdinaryName(S, PCC_Expression);
6852 else
6853 CodeCompleteExpression(S, PreferredType);
6854 return;
6855 }
6856
Fangrui Song050229d2018-11-24 00:14:31 +00006857 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006858 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006859}
6860
Richard Trieu2bd04012011-09-09 02:00:50 +00006861void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006862 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006863 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006864 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006865 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006866
Steve Naroffeae65032009-11-07 02:08:14 +00006867 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006868
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006869 // If necessary, apply function/array conversion to the receiver.
6870 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006871 if (RecExpr) {
6872 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6873 if (Conv.isInvalid()) // conversion failed. bail.
6874 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006875 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006876 }
Fangrui Song050229d2018-11-24 00:14:31 +00006877 QualType ReceiverType = RecExpr
6878 ? RecExpr->getType()
6879 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006880 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006881 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006882
Douglas Gregordc520b02010-11-08 21:12:30 +00006883 // If we're messaging an expression with type "id" or "Class", check
6884 // whether we know something special about the receiver that allows
6885 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006886 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006887 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6888 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006889 return CodeCompleteObjCClassMessage(
6890 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6891 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006892
Fangrui Song050229d2018-11-24 00:14:31 +00006893 ReceiverType =
6894 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006895 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006896 } else if (RecExpr && getLangOpts().CPlusPlus) {
6897 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6898 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006899 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006900 ReceiverType = RecExpr->getType();
6901 }
6902 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006903
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006904 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006905 ResultBuilder Results(
6906 *this, CodeCompleter->getAllocator(),
6907 CodeCompleter->getCodeCompletionTUInfo(),
6908 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6909 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006910
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006911 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006912
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006913 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006914 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006915 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006916 if (ObjCMethodDecl *SuperMethod =
6917 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006918 Results.Ignore(SuperMethod);
6919 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006920
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006921 // If we're inside an Objective-C method definition, prefer its selector to
6922 // others.
6923 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6924 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006925
Douglas Gregor1154e272010-09-16 16:06:31 +00006926 // Keep track of the selectors we've already added.
6927 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006928
Douglas Gregora3329fa2009-11-18 00:06:18 +00006929 // Handle messages to Class. This really isn't a message to an instance
6930 // method, so we treat it the same way we would treat a message send to a
6931 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006932 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006933 ReceiverType->isObjCQualifiedClassType()) {
6934 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6935 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006936 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6937 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006938 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006939 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006940 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006941 else if (const ObjCObjectPointerType *QualID =
6942 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006943 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006944 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006945 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6946 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006947 }
6948 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006949 else if (const ObjCObjectPointerType *IFacePtr =
6950 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006951 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006952 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006953 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006954
Douglas Gregora3329fa2009-11-18 00:06:18 +00006955 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006956 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006957 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6958 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006959 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006960 // Handle messages to "id".
6961 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006962 // We're messaging "id", so provide all instance methods we know
6963 // about as code-completion results.
6964
6965 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006966 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006967 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006968 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6969 I != N; ++I) {
6970 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006971 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006972 continue;
6973
Sebastian Redl75d8a322010-08-02 23:18:59 +00006974 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006975 }
6976 }
6977
Sebastian Redl75d8a322010-08-02 23:18:59 +00006978 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6979 MEnd = MethodPool.end();
6980 M != MEnd; ++M) {
6981 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006982 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006983 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006984 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006985
Nico Weber2e0c8f72014-12-27 03:58:08 +00006986 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006987 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006988
Nico Weber2e0c8f72014-12-27 03:58:08 +00006989 Result R(MethList->getMethod(),
6990 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006991 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006992 R.AllParametersAreInformative = false;
6993 Results.MaybeAddResult(R, CurContext);
6994 }
6995 }
6996 }
Steve Naroffeae65032009-11-07 02:08:14 +00006997 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006998
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006999 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00007000 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007001 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00007002 // code-complete the expression using the corresponding parameter type as
7003 // our preferred type, improving completion results.
7004 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00007005 QualType PreferredType =
7006 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00007007 if (PreferredType.isNull())
7008 CodeCompleteOrdinaryName(S, PCC_Expression);
7009 else
7010 CodeCompleteExpression(S, PreferredType);
7011 return;
7012 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007013
Fangrui Song050229d2018-11-24 00:14:31 +00007014 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7015 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00007016}
Douglas Gregorbaf69612009-11-18 04:19:12 +00007017
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007018void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00007019 DeclGroupPtrTy IterationVar) {
7020 CodeCompleteExpressionData Data;
7021 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007022
Douglas Gregor68762e72010-08-23 21:17:50 +00007023 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00007024 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00007025 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
7026 if (*I)
7027 Data.IgnoreDecls.push_back(*I);
7028 }
7029 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007030
Douglas Gregor68762e72010-08-23 21:17:50 +00007031 CodeCompleteExpression(S, Data);
7032}
7033
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007034void Sema::CodeCompleteObjCSelector(Scope *S,
7035 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007036 // If we have an external source, load the entire class method
7037 // pool from the AST file.
7038 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00007039 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
7040 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007041 Selector Sel = ExternalSource->GetExternalSelector(I);
7042 if (Sel.isNull() || MethodPool.count(Sel))
7043 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007044
Douglas Gregor67c692c2010-08-26 15:07:07 +00007045 ReadMethodPool(Sel);
7046 }
7047 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007048
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007049 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007050 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007051 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00007052 Results.EnterNewScope();
7053 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007054 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00007055 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007056
Douglas Gregor67c692c2010-08-26 15:07:07 +00007057 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007058 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00007059 continue;
7060
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007061 CodeCompletionBuilder Builder(Results.getAllocator(),
7062 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007063 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007064 Builder.AddTypedTextChunk(
7065 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007066 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007067 continue;
7068 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007069
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007070 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00007071 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007072 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007073 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007074 Builder.AddInformativeChunk(
7075 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007076 Accumulator.clear();
7077 }
7078 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007079
Benjamin Kramer632500c2011-07-26 16:59:25 +00007080 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007081 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00007082 }
Fangrui Song050229d2018-11-24 00:14:31 +00007083 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007084 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007085 }
7086 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007087
7088 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00007089 Results.data(), Results.size());
7090}
7091
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007092/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00007093/// (translation unit) context.
7094static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007095 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00007096 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007097 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007098
Aaron Ballman629afae2014-03-07 19:56:05 +00007099 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00007100 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007101 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00007102 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00007103 Results.AddResult(
7104 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
7105 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007106 }
7107}
7108
Craig Topper883dd332015-12-24 23:58:11 +00007109void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00007110 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007111 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007112 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007113 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007114
Chandler Carruthede11632016-11-04 06:06:50 +00007115 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007116 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007117
Douglas Gregora3b23b02010-12-09 21:44:02 +00007118 // Tell the result set to ignore all of the protocols we have
7119 // already seen.
7120 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00007121 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00007122 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00007123 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007124
Douglas Gregora3b23b02010-12-09 21:44:02 +00007125 // Add all protocols.
7126 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
7127 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007128
Douglas Gregora3b23b02010-12-09 21:44:02 +00007129 Results.ExitScope();
7130 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00007131
7132 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7133 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007134}
7135
7136void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007137 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007138 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007139 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007140
Chandler Carruthede11632016-11-04 06:06:50 +00007141 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007142 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007143
Douglas Gregora3b23b02010-12-09 21:44:02 +00007144 // Add all protocols.
7145 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
7146 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007147
Douglas Gregora3b23b02010-12-09 21:44:02 +00007148 Results.ExitScope();
7149 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00007150
7151 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7152 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00007153}
Douglas Gregor49c22a72009-11-18 16:26:39 +00007154
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007155/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00007156/// the given (translation unit) context.
7157static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
7158 bool OnlyForwardDeclarations,
7159 bool OnlyUnimplemented,
7160 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007161 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007162
Aaron Ballman629afae2014-03-07 19:56:05 +00007163 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00007164 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007165 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00007166 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00007167 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00007168 Results.AddResult(
7169 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
7170 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007171 }
7172}
7173
Eric Liuf5ba09f2018-07-04 10:01:18 +00007174void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007175 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007176 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007177 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007178 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007179
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007180 if (CodeCompleter->includeGlobals()) {
7181 // Add all classes.
7182 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7183 false, Results);
7184 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007185
Douglas Gregor49c22a72009-11-18 16:26:39 +00007186 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007187
Eric Liuf5ba09f2018-07-04 10:01:18 +00007188 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7189 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007190}
7191
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007192void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007193 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007194 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007195 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007196 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007197 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007198
Douglas Gregor49c22a72009-11-18 16:26:39 +00007199 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00007200 NamedDecl *CurClass =
7201 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007202 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00007203 Results.Ignore(CurClass);
7204
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007205 if (CodeCompleter->includeGlobals()) {
7206 // Add all classes.
7207 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7208 false, Results);
7209 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007210
Douglas Gregor49c22a72009-11-18 16:26:39 +00007211 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007212
Eric Liuf5ba09f2018-07-04 10:01:18 +00007213 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7214 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007215}
7216
Eric Liuf5ba09f2018-07-04 10:01:18 +00007217void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007218 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007219 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007220 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007221 Results.EnterNewScope();
7222
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007223 if (CodeCompleter->includeGlobals()) {
7224 // Add all unimplemented classes.
7225 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7226 true, Results);
7227 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007228
Douglas Gregor49c22a72009-11-18 16:26:39 +00007229 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007230
Eric Liuf5ba09f2018-07-04 10:01:18 +00007231 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7232 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007233}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007234
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007235void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007236 IdentifierInfo *ClassName,
7237 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007238 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007239
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007240 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007241 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007242 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007243
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007244 // Ignore any categories we find that have already been implemented by this
7245 // interface.
7246 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00007247 NamedDecl *CurClass =
7248 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
7249 if (ObjCInterfaceDecl *Class =
7250 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007251 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007252 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007253 }
7254
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007255 // Add all of the categories we know about.
7256 Results.EnterNewScope();
7257 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007258 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00007259 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00007260 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00007261 Results.AddResult(
7262 Result(Category, Results.getBasePriority(Category), nullptr),
7263 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007264 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007265
7266 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7267 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007268}
7269
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007270void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007271 IdentifierInfo *ClassName,
7272 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007273 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007274
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007275 // Find the corresponding interface. If we couldn't find the interface, the
7276 // program itself is ill-formed. However, we'll try to be helpful still by
7277 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00007278 NamedDecl *CurClass =
7279 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007280 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
7281 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007282 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007283
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007284 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007285 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007286 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007287
7288 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007289 // declarations in this class and any of its superclasses, except for
7290 // already-implemented categories in the class itself.
7291 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7292 Results.EnterNewScope();
7293 bool IgnoreImplemented = true;
7294 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007295 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007296 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007297 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007298 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7299 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007300 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007301
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007302 Class = Class->getSuperClass();
7303 IgnoreImplemented = false;
7304 }
7305 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007306
7307 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7308 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007309}
Douglas Gregor5d649882009-11-18 22:32:06 +00007310
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007311void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007312 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007313 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007314 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007315
7316 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007317 ObjCContainerDecl *Container =
7318 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7319 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7320 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007321 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007322
7323 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007324 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007325 for (const auto *D : Container->decls())
7326 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007327 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007328
Douglas Gregor5d649882009-11-18 22:32:06 +00007329 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007330 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007331 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007332 if (ObjCImplementationDecl *ClassImpl =
7333 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007334 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007335 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007336 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007337 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007338 AddObjCProperties(CCContext,
7339 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007340 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007341 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007342 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007343
7344 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7345 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007346}
7347
Fangrui Song050229d2018-11-24 00:14:31 +00007348void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7349 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007350 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007351 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007352 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007353 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007354
7355 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007356 ObjCContainerDecl *Container =
7357 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7358 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7359 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007360 return;
7361
Douglas Gregor5d649882009-11-18 22:32:06 +00007362 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007363 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007364 if (ObjCImplementationDecl *ClassImpl =
7365 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007366 Class = ClassImpl->getClassInterface();
7367 else
Fangrui Song050229d2018-11-24 00:14:31 +00007368 Class = cast<ObjCCategoryImplDecl>(Container)
7369 ->getCategoryDecl()
7370 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007371
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007372 // Determine the type of the property we're synthesizing.
7373 QualType PropertyType = Context.getObjCIdType();
7374 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007375 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7376 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007377 PropertyType =
7378 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007379
7380 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007381 Results.setPreferredType(PropertyType);
7382 }
7383 }
7384
Douglas Gregor5d649882009-11-18 22:32:06 +00007385 // Add all of the instance variables in this class and its superclasses.
7386 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007387 bool SawSimilarlyNamedIvar = false;
7388 std::string NameWithPrefix;
7389 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007390 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007391 std::string NameWithSuffix = PropertyName->getName().str();
7392 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007393 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007394 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007395 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007396 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7397 CurContext, nullptr, false);
7398
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007399 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007400 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007401 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007402 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007403 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007404 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007405
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007406 // Reduce the priority of this result by one, to give it a slight
7407 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007408 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007409 Results.data()[Results.size() - 1].Kind ==
7410 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007411 Results.data()[Results.size() - 1].Declaration == Ivar)
7412 Results.data()[Results.size() - 1].Priority--;
7413 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007414 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007415 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007416
Douglas Gregor331faa02011-04-18 14:13:53 +00007417 if (!SawSimilarlyNamedIvar) {
7418 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007419 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007420 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007421 typedef CodeCompletionResult Result;
7422 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007423 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007424 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007425
Douglas Gregor75acd922011-09-27 23:30:47 +00007426 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007427 Builder.AddResultTypeChunk(
7428 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007429 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007430 Results.AddResult(
7431 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007432 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007433
Douglas Gregor5d649882009-11-18 22:32:06 +00007434 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007435
7436 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7437 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007438}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007439
Douglas Gregor416b5752010-08-25 01:08:01 +00007440// Mapping from selectors to the methods that implement that selector, along
7441// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007442typedef llvm::DenseMap<Selector,
7443 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7444 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007445
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007446/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007447/// (and its superclasses, protocols, etc.) that meet the given
7448/// criteria. Insert those methods into the map of known methods,
7449/// indexed by selector so they can be easily found.
7450static void FindImplementableMethods(ASTContext &Context,
7451 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007452 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007453 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007454 KnownMethodsMap &KnownMethods,
7455 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007456 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007457 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007458 if (!IFace->hasDefinition())
7459 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007460
7461 IFace = IFace->getDefinition();
7462 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007463
Fangrui Song050229d2018-11-24 00:14:31 +00007464 const ObjCList<ObjCProtocolDecl> &Protocols =
7465 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007466 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007467 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007468 I != E; ++I)
7469 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007470 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007471
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007472 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007473 for (auto *Cat : IFace->visible_categories()) {
7474 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007475 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007476 }
7477
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007478 // Visit the superclass.
7479 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007480 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007481 WantInstanceMethods, ReturnType, KnownMethods,
7482 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007483 }
7484
7485 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7486 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007487 const ObjCList<ObjCProtocolDecl> &Protocols =
7488 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007489 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007490 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007491 I != E; ++I)
7492 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007493 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007494
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007495 // If this category is the original class, jump to the interface.
7496 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007497 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007498 WantInstanceMethods, ReturnType, KnownMethods,
7499 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007500 }
7501
7502 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007503 // Make sure we have a definition; that's what we'll walk.
7504 if (!Protocol->hasDefinition())
7505 return;
7506 Protocol = Protocol->getDefinition();
7507 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007508
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007509 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007510 const ObjCList<ObjCProtocolDecl> &Protocols =
7511 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007512 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007513 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007514 I != E; ++I)
7515 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7516 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007517 }
7518
7519 // Add methods in this container. This operation occurs last because
7520 // we want the methods from this container to override any methods
7521 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007522 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007523 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007524 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007525 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007526 continue;
7527
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007528 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007529 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007530 }
7531 }
7532}
7533
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007534/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007535/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007536static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007537 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007538 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007539 CodeCompletionBuilder &Builder) {
7540 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007541 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007542 if (!Quals.empty())
7543 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007544 Builder.AddTextChunk(
7545 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007546 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7547}
7548
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007549/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007550/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007551static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007552 if (!Class)
7553 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007554
Douglas Gregor669a25a2011-02-17 00:22:45 +00007555 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7556 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007557
Douglas Gregor669a25a2011-02-17 00:22:45 +00007558 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7559}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007560
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007561/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007562/// Key-Value Observing (KVO).
7563static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7564 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007565 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007566 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007567 ResultBuilder &Results) {
7568 IdentifierInfo *PropName = Property->getIdentifier();
7569 if (!PropName || PropName->getLength() == 0)
7570 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007571
Douglas Gregor75acd922011-09-27 23:30:47 +00007572 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7573
Douglas Gregor669a25a2011-02-17 00:22:45 +00007574 // Builder that will create each code completion.
7575 typedef CodeCompletionResult Result;
7576 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007577 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007578
Douglas Gregor669a25a2011-02-17 00:22:45 +00007579 // The selector table.
7580 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007581
Douglas Gregor669a25a2011-02-17 00:22:45 +00007582 // The property name, copied into the code completion allocation region
7583 // on demand.
7584 struct KeyHolder {
7585 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007586 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007587 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007588
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007589 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007590 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007591
Douglas Gregor669a25a2011-02-17 00:22:45 +00007592 operator const char *() {
7593 if (CopiedKey)
7594 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007595
Douglas Gregor669a25a2011-02-17 00:22:45 +00007596 return CopiedKey = Allocator.CopyString(Key);
7597 }
7598 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007599
Douglas Gregor669a25a2011-02-17 00:22:45 +00007600 // The uppercased name of the property name.
7601 std::string UpperKey = PropName->getName();
7602 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007603 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007604
Fangrui Song050229d2018-11-24 00:14:31 +00007605 bool ReturnTypeMatchesProperty =
7606 ReturnType.isNull() ||
7607 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7608 Property->getType());
7609 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007610
Douglas Gregor669a25a2011-02-17 00:22:45 +00007611 // Add the normal accessor -(type)key.
7612 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007613 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007614 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7615 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007616 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7617 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007618
Douglas Gregor669a25a2011-02-17 00:22:45 +00007619 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007620 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007621 CXCursor_ObjCInstanceMethodDecl));
7622 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007623
Douglas Gregor669a25a2011-02-17 00:22:45 +00007624 // If we have an integral or boolean property (or the user has provided
7625 // an integral or boolean return type), add the accessor -(type)isKey.
7626 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007627 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007628 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007629 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7630 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007631 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007632 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007633 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7634 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007635 if (ReturnType.isNull()) {
7636 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7637 Builder.AddTextChunk("BOOL");
7638 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7639 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007640
Fangrui Song050229d2018-11-24 00:14:31 +00007641 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007642 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007643 CXCursor_ObjCInstanceMethodDecl));
7644 }
7645 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007646
Douglas Gregor669a25a2011-02-17 00:22:45 +00007647 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007648 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007649 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007650 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007651 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007652 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007653 if (ReturnType.isNull()) {
7654 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7655 Builder.AddTextChunk("void");
7656 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7657 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007658
Fangrui Song050229d2018-11-24 00:14:31 +00007659 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007660 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007661 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7662 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007663 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007664 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007665 CXCursor_ObjCInstanceMethodDecl));
7666 }
7667 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007668
Douglas Gregor669a25a2011-02-17 00:22:45 +00007669 // Indexed and unordered accessors
7670 unsigned IndexedGetterPriority = CCP_CodePattern;
7671 unsigned IndexedSetterPriority = CCP_CodePattern;
7672 unsigned UnorderedGetterPriority = CCP_CodePattern;
7673 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007674 if (const auto *ObjCPointer =
7675 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007676 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7677 // If this interface type is not provably derived from a known
7678 // collection, penalize the corresponding completions.
7679 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007680 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007681 if (!InheritsFromClassNamed(IFace, "NSArray"))
7682 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7683 }
7684
7685 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007686 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007687 if (!InheritsFromClassNamed(IFace, "NSSet"))
7688 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7689 }
7690 }
7691 } else {
7692 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7693 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7694 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7695 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7696 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007697
Douglas Gregor669a25a2011-02-17 00:22:45 +00007698 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007699 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007700 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007701 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007702 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007703 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7704 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007705 if (ReturnType.isNull()) {
7706 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7707 Builder.AddTextChunk("NSUInteger");
7708 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7709 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007710
Fangrui Song050229d2018-11-24 00:14:31 +00007711 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7712 Results.AddResult(
7713 Result(Builder.TakeString(),
7714 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7715 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007716 }
7717 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007718
Douglas Gregor669a25a2011-02-17 00:22:45 +00007719 // Indexed getters
7720 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7721 if (IsInstanceMethod &&
7722 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007723 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007724 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007725 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007726 if (ReturnType.isNull()) {
7727 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7728 Builder.AddTextChunk("id");
7729 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7730 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007731
Douglas Gregor669a25a2011-02-17 00:22:45 +00007732 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7733 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7734 Builder.AddTextChunk("NSUInteger");
7735 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7736 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007737 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007738 CXCursor_ObjCInstanceMethodDecl));
7739 }
7740 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007741
Douglas Gregor669a25a2011-02-17 00:22:45 +00007742 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7743 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007744 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007745 (ReturnType->isObjCObjectPointerType() &&
7746 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007747 ReturnType->getAs<ObjCObjectPointerType>()
7748 ->getInterfaceDecl()
7749 ->getName() == "NSArray"))) {
7750 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007751 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007752 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007753 if (ReturnType.isNull()) {
7754 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7755 Builder.AddTextChunk("NSArray *");
7756 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7757 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007758
Douglas Gregor669a25a2011-02-17 00:22:45 +00007759 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7760 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7761 Builder.AddTextChunk("NSIndexSet *");
7762 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7763 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007764 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007765 CXCursor_ObjCInstanceMethodDecl));
7766 }
7767 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007768
Douglas Gregor669a25a2011-02-17 00:22:45 +00007769 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7770 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007771 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007772 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7773 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007774
David Blaikie82e95a32014-11-19 07:49:47 +00007775 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007776 if (ReturnType.isNull()) {
7777 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7778 Builder.AddTextChunk("void");
7779 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7780 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007781
Douglas Gregor669a25a2011-02-17 00:22:45 +00007782 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7783 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7784 Builder.AddPlaceholderChunk("object-type");
7785 Builder.AddTextChunk(" **");
7786 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7787 Builder.AddTextChunk("buffer");
7788 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7789 Builder.AddTypedTextChunk("range:");
7790 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7791 Builder.AddTextChunk("NSRange");
7792 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7793 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007794 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007795 CXCursor_ObjCInstanceMethodDecl));
7796 }
7797 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007798
Douglas Gregor669a25a2011-02-17 00:22:45 +00007799 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007800
Douglas Gregor669a25a2011-02-17 00:22:45 +00007801 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7802 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007803 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007804 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7805 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007806
David Blaikie82e95a32014-11-19 07:49:47 +00007807 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007808 if (ReturnType.isNull()) {
7809 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7810 Builder.AddTextChunk("void");
7811 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7812 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007813
Douglas Gregor669a25a2011-02-17 00:22:45 +00007814 Builder.AddTypedTextChunk("insertObject:");
7815 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7816 Builder.AddPlaceholderChunk("object-type");
7817 Builder.AddTextChunk(" *");
7818 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7819 Builder.AddTextChunk("object");
7820 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7821 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7822 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7823 Builder.AddPlaceholderChunk("NSUInteger");
7824 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7825 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007826 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007827 CXCursor_ObjCInstanceMethodDecl));
7828 }
7829 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007830
Douglas Gregor669a25a2011-02-17 00:22:45 +00007831 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7832 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007833 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007834 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7835 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007836
David Blaikie82e95a32014-11-19 07:49:47 +00007837 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007838 if (ReturnType.isNull()) {
7839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7840 Builder.AddTextChunk("void");
7841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7842 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007843
Douglas Gregor669a25a2011-02-17 00:22:45 +00007844 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7845 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7846 Builder.AddTextChunk("NSArray *");
7847 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7848 Builder.AddTextChunk("array");
7849 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7850 Builder.AddTypedTextChunk("atIndexes:");
7851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7852 Builder.AddPlaceholderChunk("NSIndexSet *");
7853 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7854 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007855 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007856 CXCursor_ObjCInstanceMethodDecl));
7857 }
7858 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007859
Douglas Gregor669a25a2011-02-17 00:22:45 +00007860 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7861 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007862 std::string SelectorName =
7863 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37: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("NSUInteger");
7875 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7876 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007877 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007878 CXCursor_ObjCInstanceMethodDecl));
7879 }
7880 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007881
Douglas Gregor669a25a2011-02-17 00:22:45 +00007882 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7883 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007884 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007885 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007886 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007887 if (ReturnType.isNull()) {
7888 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7889 Builder.AddTextChunk("void");
7890 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7891 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007892
Douglas Gregor669a25a2011-02-17 00:22:45 +00007893 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7894 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7895 Builder.AddTextChunk("NSIndexSet *");
7896 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7897 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007898 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007899 CXCursor_ObjCInstanceMethodDecl));
7900 }
7901 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007902
Douglas Gregor669a25a2011-02-17 00:22:45 +00007903 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7904 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007905 std::string SelectorName =
7906 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7907 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7908 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007909
David Blaikie82e95a32014-11-19 07:49:47 +00007910 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007911 if (ReturnType.isNull()) {
7912 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7913 Builder.AddTextChunk("void");
7914 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7915 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007916
Douglas Gregor669a25a2011-02-17 00:22:45 +00007917 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7919 Builder.AddPlaceholderChunk("NSUInteger");
7920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7921 Builder.AddTextChunk("index");
7922 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7923 Builder.AddTypedTextChunk("withObject:");
7924 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7925 Builder.AddTextChunk("id");
7926 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7927 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007928 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007929 CXCursor_ObjCInstanceMethodDecl));
7930 }
7931 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007932
Douglas Gregor669a25a2011-02-17 00:22:45 +00007933 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7934 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007935 std::string SelectorName1 =
7936 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007937 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007938 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7939 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007940
David Blaikie82e95a32014-11-19 07:49:47 +00007941 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007942 if (ReturnType.isNull()) {
7943 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7944 Builder.AddTextChunk("void");
7945 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7946 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007947
Douglas Gregor669a25a2011-02-17 00:22:45 +00007948 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7949 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7950 Builder.AddPlaceholderChunk("NSIndexSet *");
7951 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7952 Builder.AddTextChunk("indexes");
7953 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7954 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7955 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7956 Builder.AddTextChunk("NSArray *");
7957 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7958 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007959 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007960 CXCursor_ObjCInstanceMethodDecl));
7961 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007962 }
7963
Douglas Gregor669a25a2011-02-17 00:22:45 +00007964 // Unordered getters
7965 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007966 if (IsInstanceMethod &&
7967 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007968 (ReturnType->isObjCObjectPointerType() &&
7969 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007970 ReturnType->getAs<ObjCObjectPointerType>()
7971 ->getInterfaceDecl()
7972 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007973 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007974 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007975 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7976 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007977 if (ReturnType.isNull()) {
7978 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7979 Builder.AddTextChunk("NSEnumerator *");
7980 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7981 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007982
Douglas Gregor669a25a2011-02-17 00:22:45 +00007983 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007984 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007985 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007986 }
7987 }
7988
7989 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007990 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007991 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007992 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007993 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007994 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007995 if (ReturnType.isNull()) {
7996 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7997 Builder.AddPlaceholderChunk("object-type");
7998 Builder.AddTextChunk(" *");
7999 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8000 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008001
Douglas Gregor669a25a2011-02-17 00:22:45 +00008002 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8003 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8004 if (ReturnType.isNull()) {
8005 Builder.AddPlaceholderChunk("object-type");
8006 Builder.AddTextChunk(" *");
8007 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00008008 Builder.AddTextChunk(GetCompletionTypeString(
8009 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008010 }
8011 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8012 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008013 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008014 CXCursor_ObjCInstanceMethodDecl));
8015 }
8016 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008017
Douglas Gregor669a25a2011-02-17 00:22:45 +00008018 // Mutable unordered accessors
8019 // - (void)addKeyObject:(type *)object
8020 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00008021 std::string SelectorName =
8022 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008023 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008024 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008025 if (ReturnType.isNull()) {
8026 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8027 Builder.AddTextChunk("void");
8028 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8029 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008030
Douglas Gregor669a25a2011-02-17 00:22:45 +00008031 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8032 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8033 Builder.AddPlaceholderChunk("object-type");
8034 Builder.AddTextChunk(" *");
8035 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8036 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008037 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008038 CXCursor_ObjCInstanceMethodDecl));
8039 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008040 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008041
8042 // - (void)addKey:(NSSet *)objects
8043 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008044 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008045 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008046 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008047 if (ReturnType.isNull()) {
8048 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8049 Builder.AddTextChunk("void");
8050 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8051 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008052
Douglas Gregor669a25a2011-02-17 00:22:45 +00008053 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8054 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8055 Builder.AddTextChunk("NSSet *");
8056 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8057 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008058 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008059 CXCursor_ObjCInstanceMethodDecl));
8060 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008061 }
8062
Douglas Gregor669a25a2011-02-17 00:22:45 +00008063 // - (void)removeKeyObject:(type *)object
8064 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00008065 std::string SelectorName =
8066 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008067 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008068 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008069 if (ReturnType.isNull()) {
8070 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8071 Builder.AddTextChunk("void");
8072 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8073 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008074
Douglas Gregor669a25a2011-02-17 00:22:45 +00008075 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8076 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8077 Builder.AddPlaceholderChunk("object-type");
8078 Builder.AddTextChunk(" *");
8079 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8080 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008081 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008082 CXCursor_ObjCInstanceMethodDecl));
8083 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008084 }
8085
Douglas Gregor669a25a2011-02-17 00:22:45 +00008086 // - (void)removeKey:(NSSet *)objects
8087 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008088 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008089 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008090 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008091 if (ReturnType.isNull()) {
8092 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8093 Builder.AddTextChunk("void");
8094 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8095 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008096
Douglas Gregor669a25a2011-02-17 00:22:45 +00008097 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8098 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8099 Builder.AddTextChunk("NSSet *");
8100 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8101 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008102 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008103 CXCursor_ObjCInstanceMethodDecl));
8104 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008105 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008106
8107 // - (void)intersectKey:(NSSet *)objects
8108 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008109 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008110 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008111 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008112 if (ReturnType.isNull()) {
8113 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8114 Builder.AddTextChunk("void");
8115 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8116 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008117
Douglas Gregor669a25a2011-02-17 00:22:45 +00008118 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8119 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8120 Builder.AddTextChunk("NSSet *");
8121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8122 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008123 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008124 CXCursor_ObjCInstanceMethodDecl));
8125 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008126 }
8127
Douglas Gregor669a25a2011-02-17 00:22:45 +00008128 // Key-Value Observing
8129 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008130 if (!IsInstanceMethod &&
8131 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00008132 (ReturnType->isObjCObjectPointerType() &&
8133 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00008134 ReturnType->getAs<ObjCObjectPointerType>()
8135 ->getInterfaceDecl()
8136 ->getName() == "NSSet"))) {
8137 std::string SelectorName =
8138 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008139 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008140 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8141 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008142 if (ReturnType.isNull()) {
8143 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00008144 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00008145 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8146 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008147
Douglas Gregor669a25a2011-02-17 00:22:45 +00008148 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008149 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008150 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00008151 }
8152 }
8153
8154 // + (BOOL)automaticallyNotifiesObserversForKey
8155 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00008156 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00008157 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00008158 std::string SelectorName =
8159 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00008160 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008161 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8162 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00008163 if (ReturnType.isNull()) {
8164 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8165 Builder.AddTextChunk("BOOL");
8166 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8167 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008168
Douglas Gregor857bcda2011-06-02 04:02:27 +00008169 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008170 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008171 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008172 }
8173 }
8174}
8175
Alex Lorenzb8740422017-10-24 16:39:37 +00008176void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008177 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008178 // Determine the return type of the method we're declaring, if
8179 // provided.
8180 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00008181 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008182 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00008183 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
8184 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008185 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008186 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00008187 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00008188 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00008189 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008190 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
8191 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008192 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00008193 } else if (ObjCCategoryImplDecl *CatImpl =
8194 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008195 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008196 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008197 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00008198 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008199 }
8200
8201 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00008202 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00008203 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008204 }
8205
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008206 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008207 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008208 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008209 return;
8210 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008211
Douglas Gregor636a61e2010-04-07 00:21:17 +00008212 // Find all of the methods that we could declare/implement here.
8213 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00008214 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
8215 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008216
Douglas Gregor636a61e2010-04-07 00:21:17 +00008217 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00008218 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008219 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008220 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008221 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008222 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00008223 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008224 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008225 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008226 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008227 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008228 CodeCompletionBuilder Builder(Results.getAllocator(),
8229 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00008230
8231 // Add the '-'/'+' prefix if it wasn't provided yet.
8232 if (!IsInstanceMethod) {
8233 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
8234 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8235 }
8236
Douglas Gregor636a61e2010-04-07 00:21:17 +00008237 // If the result type was not already provided, add it to the
8238 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008239 if (ReturnType.isNull()) {
8240 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
8241 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00008242 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
8243 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008244 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008245
8246 Selector Sel = Method->getSelector();
8247
8248 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00008249 Builder.AddTypedTextChunk(
8250 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008251
8252 // Add parameters to the pattern.
8253 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008254 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008255 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008256 P != PEnd; (void)++P, ++I) {
8257 // Add the part of the selector name.
8258 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008259 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00008260 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008261 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8262 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00008263 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008264 } else
8265 break;
8266
8267 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00008268 QualType ParamType;
8269 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
8270 ParamType = (*P)->getType();
8271 else
8272 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00008273 ParamType = ParamType.substObjCTypeArgs(
8274 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008275 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00008276 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
8277 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008278
Douglas Gregor636a61e2010-04-07 00:21:17 +00008279 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00008280 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008281 }
8282
8283 if (Method->isVariadic()) {
8284 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008285 Builder.AddChunk(CodeCompletionString::CK_Comma);
8286 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008287 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008288
Douglas Gregord37c59d2010-05-28 00:57:46 +00008289 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008290 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008291 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8292 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8293 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008294 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008295 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008296 Builder.AddTextChunk("return");
8297 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8298 Builder.AddPlaceholderChunk("expression");
8299 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008300 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008301 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008302
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008303 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8304 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008305 }
8306
Douglas Gregor416b5752010-08-25 01:08:01 +00008307 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008308 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008309 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008310 setInBaseClass(R);
8311 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008312 }
8313
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008314 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008315 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008316 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008317 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008318 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008319
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008320 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008321 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008322 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008323 M != MEnd; ++M)
8324 KnownSelectors.insert(M->first);
8325
Douglas Gregor669a25a2011-02-17 00:22:45 +00008326 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8327 if (!IFace)
8328 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8329 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008330
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008331 if (IFace)
8332 for (auto *Cat : IFace->visible_categories())
8333 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008334
8335 if (IsInstanceMethod) {
8336 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8337 for (auto *P : Containers[I]->instance_properties())
8338 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8339 KnownSelectors, Results);
8340 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008341 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008342
Douglas Gregor636a61e2010-04-07 00:21:17 +00008343 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008344
8345 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8346 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008347}
Douglas Gregor95887f92010-07-08 23:20:03 +00008348
Fangrui Song050229d2018-11-24 00:14:31 +00008349void Sema::CodeCompleteObjCMethodDeclSelector(
8350 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8351 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008352 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008353 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008354 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008355 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8356 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008357 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008358 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008359 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008360
8361 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008362 }
8363 }
8364
8365 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008366 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008367 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008368 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008369 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008370
Douglas Gregor95887f92010-07-08 23:20:03 +00008371 if (ReturnTy)
8372 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008373
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008374 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008375 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8376 MEnd = MethodPool.end();
8377 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008378 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8379 : &M->second.second;
8380 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008381 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008382 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008383
Douglas Gregor45879692010-07-08 23:37:41 +00008384 if (AtParameterName) {
8385 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008386 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008387 if (NumSelIdents &&
8388 NumSelIdents <= MethList->getMethod()->param_size()) {
8389 ParmVarDecl *Param =
8390 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008391 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008392 CodeCompletionBuilder Builder(Results.getAllocator(),
8393 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008394 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008395 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008396 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008397 }
8398 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008399
Douglas Gregor45879692010-07-08 23:37:41 +00008400 continue;
8401 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008402
Nico Weber2e0c8f72014-12-27 03:58:08 +00008403 Result R(MethList->getMethod(),
8404 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008405 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008406 R.AllParametersAreInformative = false;
8407 R.DeclaringEntity = true;
8408 Results.MaybeAddResult(R, CurContext);
8409 }
8410 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008411
Douglas Gregor95887f92010-07-08 23:20:03 +00008412 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008413
8414 if (!AtParameterName && !SelIdents.empty() &&
8415 SelIdents.front()->getName().startswith("init")) {
8416 for (const auto &M : PP.macros()) {
8417 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8418 continue;
8419 Results.EnterNewScope();
8420 CodeCompletionBuilder Builder(Results.getAllocator(),
8421 Results.getCodeCompletionTUInfo());
8422 Builder.AddTypedTextChunk(
8423 Builder.getAllocator().CopyString(M.first->getName()));
8424 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8425 CXCursor_MacroDefinition));
8426 Results.ExitScope();
8427 }
8428 }
8429
Eric Liuf5ba09f2018-07-04 10:01:18 +00008430 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8431 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008432}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008433
Douglas Gregorec00a262010-08-24 22:20:20 +00008434void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008435 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008436 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008437 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008438 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008439
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008440 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008441 CodeCompletionBuilder Builder(Results.getAllocator(),
8442 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008443 Builder.AddTypedTextChunk("if");
8444 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8445 Builder.AddPlaceholderChunk("condition");
8446 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008447
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008448 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008449 Builder.AddTypedTextChunk("ifdef");
8450 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8451 Builder.AddPlaceholderChunk("macro");
8452 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008453
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008454 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008455 Builder.AddTypedTextChunk("ifndef");
8456 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8457 Builder.AddPlaceholderChunk("macro");
8458 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008459
8460 if (InConditional) {
8461 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008462 Builder.AddTypedTextChunk("elif");
8463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8464 Builder.AddPlaceholderChunk("condition");
8465 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008466
8467 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008468 Builder.AddTypedTextChunk("else");
8469 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008470
8471 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008472 Builder.AddTypedTextChunk("endif");
8473 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008474 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008475
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008476 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008477 Builder.AddTypedTextChunk("include");
8478 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8479 Builder.AddTextChunk("\"");
8480 Builder.AddPlaceholderChunk("header");
8481 Builder.AddTextChunk("\"");
8482 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008483
8484 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008485 Builder.AddTypedTextChunk("include");
8486 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8487 Builder.AddTextChunk("<");
8488 Builder.AddPlaceholderChunk("header");
8489 Builder.AddTextChunk(">");
8490 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008491
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008492 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008493 Builder.AddTypedTextChunk("define");
8494 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8495 Builder.AddPlaceholderChunk("macro");
8496 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008497
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008498 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008499 Builder.AddTypedTextChunk("define");
8500 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8501 Builder.AddPlaceholderChunk("macro");
8502 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8503 Builder.AddPlaceholderChunk("args");
8504 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8505 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008506
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008507 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008508 Builder.AddTypedTextChunk("undef");
8509 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8510 Builder.AddPlaceholderChunk("macro");
8511 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008512
8513 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008514 Builder.AddTypedTextChunk("line");
8515 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8516 Builder.AddPlaceholderChunk("number");
8517 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008518
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008519 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008520 Builder.AddTypedTextChunk("line");
8521 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8522 Builder.AddPlaceholderChunk("number");
8523 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8524 Builder.AddTextChunk("\"");
8525 Builder.AddPlaceholderChunk("filename");
8526 Builder.AddTextChunk("\"");
8527 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008528
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008529 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008530 Builder.AddTypedTextChunk("error");
8531 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8532 Builder.AddPlaceholderChunk("message");
8533 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008534
8535 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008536 Builder.AddTypedTextChunk("pragma");
8537 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8538 Builder.AddPlaceholderChunk("arguments");
8539 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008540
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008541 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008542 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008543 Builder.AddTypedTextChunk("import");
8544 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8545 Builder.AddTextChunk("\"");
8546 Builder.AddPlaceholderChunk("header");
8547 Builder.AddTextChunk("\"");
8548 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008549
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008550 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008551 Builder.AddTypedTextChunk("import");
8552 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8553 Builder.AddTextChunk("<");
8554 Builder.AddPlaceholderChunk("header");
8555 Builder.AddTextChunk(">");
8556 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008557 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008558
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008559 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008560 Builder.AddTypedTextChunk("include_next");
8561 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8562 Builder.AddTextChunk("\"");
8563 Builder.AddPlaceholderChunk("header");
8564 Builder.AddTextChunk("\"");
8565 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008566
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008567 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008568 Builder.AddTypedTextChunk("include_next");
8569 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8570 Builder.AddTextChunk("<");
8571 Builder.AddPlaceholderChunk("header");
8572 Builder.AddTextChunk(">");
8573 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008574
8575 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008576 Builder.AddTypedTextChunk("warning");
8577 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8578 Builder.AddPlaceholderChunk("message");
8579 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008580
8581 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8582 // completions for them. And __include_macros is a Clang-internal extension
8583 // that we don't want to encourage anyone to use.
8584
8585 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8586 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008587
8588 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008589 Results.data(), Results.size());
8590}
8591
8592void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008593 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8594 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008595}
8596
Douglas Gregorec00a262010-08-24 22:20:20 +00008597void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008598 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008599 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008600 IsDefinition ? CodeCompletionContext::CCC_MacroName
8601 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008602 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008603 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008604 CodeCompletionBuilder Builder(Results.getAllocator(),
8605 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008606 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008607 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008608 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008609 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008610 Builder.AddTypedTextChunk(
8611 Builder.getAllocator().CopyString(M->first->getName()));
8612 Results.AddResult(CodeCompletionResult(
8613 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008614 }
8615 Results.ExitScope();
8616 } else if (IsDefinition) {
8617 // FIXME: Can we detect when the user just wrote an include guard above?
8618 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008619
Douglas Gregor0ac41382010-09-23 23:01:17 +00008620 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008621 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008622}
8623
Douglas Gregorec00a262010-08-24 22:20:20 +00008624void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008625 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008626 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008627 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008628
Douglas Gregorec00a262010-08-24 22:20:20 +00008629 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008630 AddMacroResults(PP, Results,
Sam McCall36082e32019-07-18 07:17:49 +00008631 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008632
Fangrui Song050229d2018-11-24 00:14:31 +00008633 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008634 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008635 CodeCompletionBuilder Builder(Results.getAllocator(),
8636 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008637 Builder.AddTypedTextChunk("defined");
8638 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8639 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8640 Builder.AddPlaceholderChunk("macro");
8641 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8642 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008643 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008644
8645 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8646 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008647}
8648
8649void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8650 IdentifierInfo *Macro,
8651 MacroInfo *MacroInfo,
8652 unsigned Argument) {
8653 // FIXME: In the future, we could provide "overload" results, much like we
8654 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008655
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008656 // Now just ignore this. There will be another code-completion callback
8657 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008658}
8659
Sam McCall3d8051a2018-09-18 08:40:41 +00008660// This handles completion inside an #include filename, e.g. #include <foo/ba
8661// We look for the directory "foo" under each directory on the include path,
8662// list its files, and reassemble the appropriate #include.
8663void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8664 // RelDir should use /, but unescaped \ is possible on windows!
8665 // Our completions will normalize to / for simplicity, this case is rare.
8666 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8667 // We need the native slashes for the actual file system interactions.
8668 SmallString<128> NativeRelDir = StringRef(RelDir);
8669 llvm::sys::path::native(NativeRelDir);
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008670 llvm::vfs::FileSystem &FS =
8671 getSourceManager().getFileManager().getVirtualFileSystem();
Sam McCall3d8051a2018-09-18 08:40:41 +00008672
8673 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8674 CodeCompleter->getCodeCompletionTUInfo(),
8675 CodeCompletionContext::CCC_IncludedFile);
8676 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8677
8678 // Helper: adds one file or directory completion result.
8679 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8680 SmallString<64> TypedChunk = Filename;
8681 // Directory completion is up to the slash, e.g. <sys/
8682 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8683 auto R = SeenResults.insert(TypedChunk);
8684 if (R.second) { // New completion
8685 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8686 *R.first = InternedTyped; // Avoid dangling StringRef.
8687 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8688 CodeCompleter->getCodeCompletionTUInfo());
8689 Builder.AddTypedTextChunk(InternedTyped);
8690 // The result is a "Pattern", which is pretty opaque.
8691 // We may want to include the real filename to allow smart ranking.
8692 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8693 }
8694 };
8695
8696 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008697 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8698 bool IsSystem,
8699 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008700 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008701 if (!NativeRelDir.empty()) {
8702 if (LookupType == DirectoryLookup::LT_Framework) {
8703 // For a framework dir, #include <Foo/Bar/> actually maps to
8704 // a path of Foo.framework/Headers/Bar/.
8705 auto Begin = llvm::sys::path::begin(NativeRelDir);
8706 auto End = llvm::sys::path::end(NativeRelDir);
8707
8708 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8709 llvm::sys::path::append(Dir, ++Begin, End);
8710 } else {
8711 llvm::sys::path::append(Dir, NativeRelDir);
8712 }
8713 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008714
8715 std::error_code EC;
8716 unsigned Count = 0;
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008717 for (auto It = FS.dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008718 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008719 if (++Count == 2500) // If we happen to hit a huge directory,
8720 break; // bail out early so we're not too slow.
8721 StringRef Filename = llvm::sys::path::filename(It->path());
8722 switch (It->type()) {
8723 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008724 // All entries in a framework directory must have a ".framework" suffix,
8725 // but the suffix does not appear in the source code's include/import.
8726 if (LookupType == DirectoryLookup::LT_Framework &&
8727 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8728 break;
8729
Sam McCall3d8051a2018-09-18 08:40:41 +00008730 AddCompletion(Filename, /*IsDirectory=*/true);
8731 break;
8732 case llvm::sys::fs::file_type::regular_file:
8733 // Only files that really look like headers. (Except in system dirs).
8734 if (!IsSystem) {
8735 // Header extensions from Types.def, which we can't depend on here.
8736 if (!(Filename.endswith_lower(".h") ||
8737 Filename.endswith_lower(".hh") ||
8738 Filename.endswith_lower(".hpp") ||
8739 Filename.endswith_lower(".inc")))
8740 break;
8741 }
8742 AddCompletion(Filename, /*IsDirectory=*/false);
8743 break;
8744 default:
8745 break;
8746 }
8747 }
8748 };
8749
8750 // Helper: adds results relative to IncludeDir, if possible.
8751 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8752 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008753 switch (IncludeDir.getLookupType()) {
8754 case DirectoryLookup::LT_HeaderMap:
8755 // header maps are not (currently) enumerable.
8756 break;
8757 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008758 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8759 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008760 break;
8761 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008762 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8763 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008764 break;
8765 }
8766 };
8767
8768 // Finally with all our helpers, we can scan the include path.
8769 // Do this in standard order so deduplication keeps the right file.
8770 // (In case we decide to add more details to the results later).
8771 const auto &S = PP.getHeaderSearchInfo();
8772 using llvm::make_range;
8773 if (!Angled) {
8774 // The current directory is on the include path for "quoted" includes.
8775 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8776 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008777 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8778 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008779 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8780 AddFilesFromDirLookup(D, false);
8781 }
8782 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008783 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008784 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8785 AddFilesFromDirLookup(D, true);
8786
8787 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8788 Results.data(), Results.size());
8789}
8790
Douglas Gregor11583702010-08-25 17:04:25 +00008791void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008792 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008793 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8794 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008795}
8796
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008797void Sema::CodeCompleteAvailabilityPlatformName() {
8798 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8799 CodeCompleter->getCodeCompletionTUInfo(),
8800 CodeCompletionContext::CCC_Other);
8801 Results.EnterNewScope();
8802 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8803 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8804 Results.AddResult(CodeCompletionResult(Platform));
8805 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8806 Twine(Platform) + "ApplicationExtension")));
8807 }
8808 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008809 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8810 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008811}
8812
Fangrui Song050229d2018-11-24 00:14:31 +00008813void Sema::GatherGlobalCodeCompletions(
8814 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8815 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008816 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8817 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008818 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008819 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008820 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008821 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8822 Consumer,
8823 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008824 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008825
Douglas Gregorb14904c2010-08-13 22:48:40 +00008826 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008827 AddMacroResults(PP, Builder,
Sam McCall36082e32019-07-18 07:17:49 +00008828 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008829
Douglas Gregorb14904c2010-08-13 22:48:40 +00008830 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008831 Results.insert(Results.end(), Builder.data(),
8832 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008833}