blob: ade6e46d1bcad6a610f1341c365d74af3a555494 [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
Alp Toker034bbd52014-06-30 01:33:53 +0000695/// Determine whether \p Id is a name reserved for the implementation (C99
696/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000697static bool isReservedName(const IdentifierInfo *Id,
698 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000699 if (Id->getLength() < 2)
700 return false;
701 const char *Name = Id->getNameStart();
702 return Name[0] == '_' &&
Fangrui Song050229d2018-11-24 00:14:31 +0000703 (Name[1] == '_' ||
704 (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000705}
706
707// Some declarations have reserved names that we don't want to ever show.
708// Filter out names reserved for the implementation if they come from a
709// system header.
710static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
711 const IdentifierInfo *Id = ND->getIdentifier();
712 if (!Id)
713 return false;
714
715 // Ignore reserved names for compiler provided decls.
716 if (isReservedName(Id) && ND->getLocation().isInvalid())
717 return true;
718
719 // For system headers ignore only double-underscore names.
720 // This allows for system headers providing private symbols with a single
721 // underscore.
722 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000723 SemaRef.SourceMgr.isInSystemHeader(
724 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
725 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000726
727 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000728}
729
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000730bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000731 bool &AsNestedNameSpecifier) const {
732 AsNestedNameSpecifier = false;
733
Richard Smithf2005d32015-12-29 23:34:32 +0000734 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000735 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000736
737 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000738 if (!ND->getDeclName())
739 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000740
Douglas Gregor3545ff42009-09-21 16:56:56 +0000741 // Friend declarations and declarations introduced due to friends are never
742 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000743 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000744 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000745
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000746 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000747 if (isa<ClassTemplateSpecializationDecl>(ND) ||
748 isa<ClassTemplatePartialSpecializationDecl>(ND))
749 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000750
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000751 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000752 if (isa<UsingDecl>(ND))
753 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000754
755 if (shouldIgnoreDueToReservedName(ND, SemaRef))
756 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000757
Douglas Gregor59cab552010-08-16 23:05:20 +0000758 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000759 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
760 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000761 AsNestedNameSpecifier = true;
762
Douglas Gregor3545ff42009-09-21 16:56:56 +0000763 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000764 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000765 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000766 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000767 IsNestedNameSpecifier(ND) &&
768 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000769 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000770 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
771 AsNestedNameSpecifier = true;
772 return true;
773 }
774
Douglas Gregor7c208612010-01-14 00:20:49 +0000775 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000776 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000777 // ... then it must be interesting!
778 return true;
779}
780
Douglas Gregore0717ab2010-01-14 00:41:07 +0000781bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000782 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000783 // In C, there is no way to refer to a hidden name.
784 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
785 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000786 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000787 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000788
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000789 const DeclContext *HiddenCtx =
790 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000791
Douglas Gregore0717ab2010-01-14 00:41:07 +0000792 // There is no way to qualify a name declared in a function or method.
793 if (HiddenCtx->isFunctionOrMethod())
794 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000795
Sebastian Redl50c68252010-08-31 00:36:30 +0000796 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000797 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000798
Douglas Gregore0717ab2010-01-14 00:41:07 +0000799 // We can refer to the result with the appropriate qualification. Do it.
800 R.Hidden = true;
801 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000802
Douglas Gregore0717ab2010-01-14 00:41:07 +0000803 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000804 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000805 R.Declaration->getDeclContext());
806 return false;
807}
808
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000809/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000810/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000811SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000812 switch (T->getTypeClass()) {
813 case Type::Builtin:
814 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000815 case BuiltinType::Void:
816 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000817
Fangrui Song050229d2018-11-24 00:14:31 +0000818 case BuiltinType::NullPtr:
819 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000820
Fangrui Song050229d2018-11-24 00:14:31 +0000821 case BuiltinType::Overload:
822 case BuiltinType::Dependent:
823 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000824
Fangrui Song050229d2018-11-24 00:14:31 +0000825 case BuiltinType::ObjCId:
826 case BuiltinType::ObjCClass:
827 case BuiltinType::ObjCSel:
828 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000829
Fangrui Song050229d2018-11-24 00:14:31 +0000830 default:
831 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000832 }
David Blaikie8a40f702012-01-17 06:56:22 +0000833
Douglas Gregor95887f92010-07-08 23:20:03 +0000834 case Type::Complex:
835 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000836
Douglas Gregor95887f92010-07-08 23:20:03 +0000837 case Type::Pointer:
838 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000839
Douglas Gregor95887f92010-07-08 23:20:03 +0000840 case Type::BlockPointer:
841 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000842
Douglas Gregor95887f92010-07-08 23:20:03 +0000843 case Type::LValueReference:
844 case Type::RValueReference:
845 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000846
Douglas Gregor95887f92010-07-08 23:20:03 +0000847 case Type::ConstantArray:
848 case Type::IncompleteArray:
849 case Type::VariableArray:
850 case Type::DependentSizedArray:
851 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000852
Douglas Gregor95887f92010-07-08 23:20:03 +0000853 case Type::DependentSizedExtVector:
854 case Type::Vector:
855 case Type::ExtVector:
856 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000857
Douglas Gregor95887f92010-07-08 23:20:03 +0000858 case Type::FunctionProto:
859 case Type::FunctionNoProto:
860 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000861
Douglas Gregor95887f92010-07-08 23:20:03 +0000862 case Type::Record:
863 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000864
Douglas Gregor95887f92010-07-08 23:20:03 +0000865 case Type::Enum:
866 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000867
Douglas Gregor95887f92010-07-08 23:20:03 +0000868 case Type::ObjCObject:
869 case Type::ObjCInterface:
870 case Type::ObjCObjectPointer:
871 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000872
Douglas Gregor95887f92010-07-08 23:20:03 +0000873 default:
874 return STC_Other;
875 }
876}
877
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000878/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000879/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000880QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000881 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000882
Fangrui Song050229d2018-11-24 00:14:31 +0000883 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000884 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000885 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000886 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000887
Douglas Gregor95887f92010-07-08 23:20:03 +0000888 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000889 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000890 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000891 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000892 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000893 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000894 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000895 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000896 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000897 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000898 T = Value->getType();
Ilya Biryukovc514ade2019-01-24 10:41:43 +0000899
900 if (T.isNull())
Douglas Gregor95887f92010-07-08 23:20:03 +0000901 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000902
903 // Dig through references, function pointers, and block pointers to
904 // get down to the likely type of an expression when the entity is
905 // used.
906 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000907 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000908 T = Ref->getPointeeType();
909 continue;
910 }
911
Fangrui Song050229d2018-11-24 00:14:31 +0000912 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000913 if (Pointer->getPointeeType()->isFunctionType()) {
914 T = Pointer->getPointeeType();
915 continue;
916 }
917
918 break;
919 }
920
Fangrui Song050229d2018-11-24 00:14:31 +0000921 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000922 T = Block->getPointeeType();
923 continue;
924 }
925
Fangrui Song050229d2018-11-24 00:14:31 +0000926 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000927 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000928 continue;
929 }
930
931 break;
932 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000933
Douglas Gregoraf670a82011-04-14 20:33:34 +0000934 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000935}
936
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000937unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
938 if (!ND)
939 return CCP_Unlikely;
940
941 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000942 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
943 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000944 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000945 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000946 if (ImplicitParam->getIdentifier() &&
947 ImplicitParam->getIdentifier()->isStr("_cmd"))
948 return CCP_ObjC_cmd;
949
950 return CCP_LocalDeclaration;
951 }
Richard Smith541b38b2013-09-20 01:15:31 +0000952
953 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000954 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
955 // Explicit destructor calls are very rare.
956 if (isa<CXXDestructorDecl>(ND))
957 return CCP_Unlikely;
958 // Explicit operator and conversion function calls are also very rare.
959 auto DeclNameKind = ND->getDeclName().getNameKind();
960 if (DeclNameKind == DeclarationName::CXXOperatorName ||
961 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
962 DeclNameKind == DeclarationName::CXXConversionFunctionName)
963 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000964 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000965 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000966
967 // Content-based decisions.
968 if (isa<EnumConstantDecl>(ND))
969 return CCP_Constant;
970
Douglas Gregor52e0de42013-01-31 05:03:46 +0000971 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
972 // message receiver, or parenthesized expression context. There, it's as
973 // likely that the user will want to write a type as other declarations.
974 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
975 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000976 CompletionContext.getKind() ==
977 CodeCompletionContext::CCC_ObjCMessageReceiver ||
978 CompletionContext.getKind() ==
979 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000980 return CCP_Type;
981
982 return CCP_Declaration;
983}
984
Douglas Gregor50832e02010-09-20 22:39:41 +0000985void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
986 // If this is an Objective-C method declaration whose selector matches our
987 // preferred selector, give it a priority boost.
988 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000989 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000990 if (PreferredSelector == Method->getSelector())
991 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000992
Douglas Gregor50832e02010-09-20 22:39:41 +0000993 // If we have a preferred type, adjust the priority for results with exactly-
994 // matching or nearly-matching types.
995 if (!PreferredType.isNull()) {
996 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
997 if (!T.isNull()) {
998 CanQualType TC = SemaRef.Context.getCanonicalType(T);
999 // Check for exactly-matching types (modulo qualifiers).
1000 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
1001 R.Priority /= CCF_ExactTypeMatch;
1002 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +00001003 else if ((getSimplifiedTypeClass(PreferredType) ==
1004 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +00001005 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001006 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +00001007 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001008 }
Douglas Gregor95887f92010-07-08 23:20:03 +00001009}
1010
Benjamin Kramer756ecb82019-02-11 14:52:15 +00001011static DeclContext::lookup_result getConstructors(ASTContext &Context,
1012 const CXXRecordDecl *Record) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001013 QualType RecordTy = Context.getTypeDeclType(Record);
1014 DeclarationName ConstructorName =
1015 Context.DeclarationNames.getCXXConstructorName(
1016 Context.getCanonicalType(RecordTy));
1017 return Record->lookup(ConstructorName);
1018}
1019
Douglas Gregor0212fd72010-09-21 16:06:22 +00001020void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001021 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +00001022 !CompletionContext.wantConstructorResults())
1023 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001024
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001025 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +00001026 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001027 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001028 Record = ClassTemplate->getTemplatedDecl();
1029 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
1030 // Skip specializations and partial specializations.
1031 if (isa<ClassTemplateSpecializationDecl>(Record))
1032 return;
1033 } else {
1034 // There are no constructors here.
1035 return;
1036 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001037
Douglas Gregor0212fd72010-09-21 16:06:22 +00001038 Record = Record->getDefinition();
1039 if (!Record)
1040 return;
1041
Fangrui Song050229d2018-11-24 00:14:31 +00001042 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00001043 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001044 R.CursorKind = getCursorKindForDecl(R.Declaration);
1045 Results.push_back(R);
1046 }
1047}
1048
Sam McCall63c59722018-01-22 20:44:47 +00001049static bool isConstructor(const Decl *ND) {
1050 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
1051 ND = Tmpl->getTemplatedDecl();
1052 return isa<CXXConstructorDecl>(ND);
1053}
1054
Douglas Gregor7c208612010-01-14 00:20:49 +00001055void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
1056 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001057
Douglas Gregor7c208612010-01-14 00:20:49 +00001058 if (R.Kind != Result::RK_Declaration) {
1059 // For non-declaration results, just add the result.
1060 Results.push_back(R);
1061 return;
1062 }
1063
1064 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001065 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
1066 CodeCompletionResult Result(Using->getTargetDecl(),
1067 getBasePriority(Using->getTargetDecl()),
1068 R.Qualifier);
1069 Result.ShadowDecl = Using;
1070 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +00001071 return;
1072 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001073
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001074 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +00001075 unsigned IDNS = CanonDecl->getIdentifierNamespace();
1076
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001077 bool AsNestedNameSpecifier = false;
1078 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +00001079 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001080
Douglas Gregor0212fd72010-09-21 16:06:22 +00001081 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001082 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001083 return;
1084
Douglas Gregor3545ff42009-09-21 16:56:56 +00001085 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001086 ShadowMapEntry::iterator I, IEnd;
1087 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
1088 if (NamePos != SMap.end()) {
1089 I = NamePos->second.begin();
1090 IEnd = NamePos->second.end();
1091 }
1092
1093 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001094 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001095 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001096 if (ND->getCanonicalDecl() == CanonDecl) {
1097 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001098 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001099
Douglas Gregor3545ff42009-09-21 16:56:56 +00001100 // We're done.
1101 return;
1102 }
1103 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001104
Douglas Gregor3545ff42009-09-21 16:56:56 +00001105 // This is a new declaration in this scope. However, check whether this
1106 // declaration name is hidden by a similarly-named declaration in an outer
1107 // scope.
1108 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
1109 --SMEnd;
1110 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001111 ShadowMapEntry::iterator I, IEnd;
1112 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
1113 if (NamePos != SM->end()) {
1114 I = NamePos->second.begin();
1115 IEnd = NamePos->second.end();
1116 }
1117 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001118 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +00001119 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +00001120 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
1121 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001122 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001123
Douglas Gregor3545ff42009-09-21 16:56:56 +00001124 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +00001125 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
1126 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001127 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001128 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001129
Douglas Gregor3545ff42009-09-21 16:56:56 +00001130 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +00001131 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001132 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001133
Douglas Gregor3545ff42009-09-21 16:56:56 +00001134 break;
1135 }
1136 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001137
Douglas Gregor3545ff42009-09-21 16:56:56 +00001138 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001139 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +00001140 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00001141
Douglas Gregore412a5a2009-09-23 22:26:46 +00001142 // If the filter is for nested-name-specifiers, then this result starts a
1143 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001144 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +00001145 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001146 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001147 } else
Fangrui Song050229d2018-11-24 00:14:31 +00001148 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001149
Douglas Gregor5bf52692009-09-22 23:15:58 +00001150 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +00001151 if (R.QualifierIsInformative && !R.Qualifier &&
1152 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001153 const DeclContext *Ctx = R.Declaration->getDeclContext();
1154 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001155 R.Qualifier =
1156 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001157 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +00001158 R.Qualifier = NestedNameSpecifier::Create(
1159 SemaRef.Context, nullptr, false,
1160 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +00001161 else
1162 R.QualifierIsInformative = false;
1163 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001164
Douglas Gregor3545ff42009-09-21 16:56:56 +00001165 // Insert this result into the set of results and into the current shadow
1166 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001167 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001168 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001169
Douglas Gregor0212fd72010-09-21 16:06:22 +00001170 if (!AsNestedNameSpecifier)
1171 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001172}
1173
Eric Liu4a7cd632018-10-24 12:57:27 +00001174static void setInBaseClass(ResultBuilder::Result &R) {
1175 R.Priority += CCD_InBaseClass;
1176 R.InBaseClass = true;
1177}
1178
Sam McCall3dea5272019-06-10 15:17:52 +00001179enum class OverloadCompare { BothViable, Dominates, Dominated };
1180// Will Candidate ever be called on the object, when overloaded with Incumbent?
1181// Returns Dominates if Candidate is always called, Dominated if Incumbent is
1182// always called, BothViable if either may be called dependending on arguments.
1183// Precondition: must actually be overloads!
1184static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate,
1185 const CXXMethodDecl &Incumbent,
1186 const Qualifiers &ObjectQuals,
1187 ExprValueKind ObjectKind) {
Ilya Biryukov8613e902019-10-04 08:10:27 +00001188 // Base/derived shadowing is handled elsewhere.
1189 if (Candidate.getDeclContext() != Incumbent.getDeclContext())
1190 return OverloadCompare::BothViable;
Sam McCall3dea5272019-06-10 15:17:52 +00001191 if (Candidate.isVariadic() != Incumbent.isVariadic() ||
1192 Candidate.getNumParams() != Incumbent.getNumParams() ||
1193 Candidate.getMinRequiredArguments() !=
1194 Incumbent.getMinRequiredArguments())
1195 return OverloadCompare::BothViable;
1196 for (unsigned I = 0, E = Candidate.getNumParams(); I != E; ++I)
1197 if (Candidate.parameters()[I]->getType().getCanonicalType() !=
1198 Incumbent.parameters()[I]->getType().getCanonicalType())
1199 return OverloadCompare::BothViable;
1200 if (!llvm::empty(Candidate.specific_attrs<EnableIfAttr>()) ||
1201 !llvm::empty(Incumbent.specific_attrs<EnableIfAttr>()))
1202 return OverloadCompare::BothViable;
1203 // At this point, we know calls can't pick one or the other based on
1204 // arguments, so one of the two must win. (Or both fail, handled elsewhere).
1205 RefQualifierKind CandidateRef = Candidate.getRefQualifier();
1206 RefQualifierKind IncumbentRef = Incumbent.getRefQualifier();
1207 if (CandidateRef != IncumbentRef) {
1208 // If the object kind is LValue/RValue, there's one acceptable ref-qualifier
1209 // and it can't be mixed with ref-unqualified overloads (in valid code).
1210
1211 // For xvalue objects, we prefer the rvalue overload even if we have to
1212 // add qualifiers (which is rare, because const&& is rare).
1213 if (ObjectKind == clang::VK_XValue)
1214 return CandidateRef == RQ_RValue ? OverloadCompare::Dominates
1215 : OverloadCompare::Dominated;
1216 }
1217 // Now the ref qualifiers are the same (or we're in some invalid state).
1218 // So make some decision based on the qualifiers.
1219 Qualifiers CandidateQual = Candidate.getMethodQualifiers();
1220 Qualifiers IncumbentQual = Incumbent.getMethodQualifiers();
1221 bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual);
1222 bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual);
1223 if (CandidateSuperset == IncumbentSuperset)
1224 return OverloadCompare::BothViable;
1225 return IncumbentSuperset ? OverloadCompare::Dominates
1226 : OverloadCompare::Dominated;
1227}
1228
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001229void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +00001230 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001231 if (R.Kind != Result::RK_Declaration) {
1232 // For non-declaration results, just add the result.
1233 Results.push_back(R);
1234 return;
1235 }
1236
Douglas Gregorc580c522010-01-14 01:09:38 +00001237 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +00001238 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001239 CodeCompletionResult Result(Using->getTargetDecl(),
1240 getBasePriority(Using->getTargetDecl()),
1241 R.Qualifier);
1242 Result.ShadowDecl = Using;
1243 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +00001244 return;
1245 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001246
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001247 bool AsNestedNameSpecifier = false;
1248 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +00001249 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001250
Douglas Gregor0212fd72010-09-21 16:06:22 +00001251 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001252 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001253 return;
1254
Douglas Gregorc580c522010-01-14 01:09:38 +00001255 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1256 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001257
Douglas Gregorc580c522010-01-14 01:09:38 +00001258 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001259 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001260 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001261
Douglas Gregorc580c522010-01-14 01:09:38 +00001262 // If the filter is for nested-name-specifiers, then this result starts a
1263 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001264 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001265 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001266 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001267 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1268 InBaseClass &&
1269 isa<CXXRecordDecl>(
1270 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001271 R.QualifierIsInformative = true;
1272
Douglas Gregorc580c522010-01-14 01:09:38 +00001273 // If this result is supposed to have an informative qualifier, add one.
1274 if (R.QualifierIsInformative && !R.Qualifier &&
1275 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001276 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001277 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1278 R.Qualifier =
1279 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1280 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1281 R.Qualifier = NestedNameSpecifier::Create(
1282 SemaRef.Context, nullptr, false,
1283 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001284 else
1285 R.QualifierIsInformative = false;
1286 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001287
Douglas Gregora2db7932010-05-26 22:00:08 +00001288 // Adjust the priority if this result comes from a base class.
1289 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001290 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001291
Douglas Gregor50832e02010-09-20 22:39:41 +00001292 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001293
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001294 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001295 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001296 if (Method->isInstance()) {
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00001297 Qualifiers MethodQuals = Method->getMethodQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001298 if (ObjectTypeQualifiers == MethodQuals)
1299 R.Priority += CCD_ObjectQualifierMatch;
1300 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001301 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001302 // qualifiers.
1303 return;
1304 }
Sam McCall3dea5272019-06-10 15:17:52 +00001305 // Detect cases where a ref-qualified method cannot be invoked.
1306 switch (Method->getRefQualifier()) {
1307 case RQ_LValue:
1308 if (ObjectKind != VK_LValue && !MethodQuals.hasConst())
1309 return;
1310 break;
1311 case RQ_RValue:
1312 if (ObjectKind == VK_LValue)
1313 return;
1314 break;
1315 case RQ_None:
1316 break;
1317 }
1318
1319 /// Check whether this dominates another overloaded method, which should
1320 /// be suppressed (or vice versa).
1321 /// Motivating case is const_iterator begin() const vs iterator begin().
1322 auto &OverloadSet = OverloadMap[std::make_pair(
1323 CurContext, Method->getDeclName().getAsOpaqueInteger())];
1324 for (const DeclIndexPair& Entry : OverloadSet) {
1325 Result &Incumbent = Results[Entry.second];
1326 switch (compareOverloads(*Method,
1327 *cast<CXXMethodDecl>(Incumbent.Declaration),
1328 ObjectTypeQualifiers, ObjectKind)) {
1329 case OverloadCompare::Dominates:
1330 // Replace the dominated overload with this one.
1331 // FIXME: if the overload dominates multiple incumbents then we
1332 // should remove all. But two overloads is by far the common case.
1333 Incumbent = std::move(R);
1334 return;
1335 case OverloadCompare::Dominated:
1336 // This overload can't be called, drop it.
1337 return;
1338 case OverloadCompare::BothViable:
1339 break;
1340 }
1341 }
1342 OverloadSet.Add(Method, Results.size());
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001343 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001344
Douglas Gregorc580c522010-01-14 01:09:38 +00001345 // Insert this result into the set of results.
1346 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001347
Douglas Gregor0212fd72010-09-21 16:06:22 +00001348 if (!AsNestedNameSpecifier)
1349 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001350}
1351
Douglas Gregor78a21012010-01-14 16:01:26 +00001352void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001353 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001354 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001355 Results.push_back(R);
1356}
1357
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001358/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001359void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001360
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001361/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001362void ResultBuilder::ExitScope() {
1363 ShadowMaps.pop_back();
1364}
1365
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001366/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001367/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001368bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001369 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001370
Richard Smith541b38b2013-09-20 01:15:31 +00001371 // If name lookup finds a local extern declaration, then we are in a
1372 // context where it behaves like an ordinary name.
1373 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001374 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001375 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001376 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001377 if (isa<ObjCIvarDecl>(ND))
1378 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001379 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001380
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001381 return ND->getIdentifierNamespace() & IDNS;
1382}
1383
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001384/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001385/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001386bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001387 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001388 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001389 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001390 // Objective-C interfaces names are not filtered by this method because they
1391 // can be used in a class property expression. We can still filter out
1392 // @class declarations though.
1393 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1394 if (!ID->getDefinition())
1395 return false;
1396 }
1397
Richard Smith541b38b2013-09-20 01:15:31 +00001398 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001399 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001400 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001401 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001402 if (isa<ObjCIvarDecl>(ND))
1403 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001404 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001405
Douglas Gregor70febae2010-05-28 00:49:12 +00001406 return ND->getIdentifierNamespace() & IDNS;
1407}
1408
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001409bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001410 if (!IsOrdinaryNonTypeName(ND))
1411 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001412
Fangrui Song050229d2018-11-24 00:14:31 +00001413 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001414 if (VD->getType()->isIntegralOrEnumerationType())
1415 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001416
Douglas Gregor85b50632010-07-28 21:50:18 +00001417 return false;
1418}
1419
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001420/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001421/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001422bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001423 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001424
Richard Smith541b38b2013-09-20 01:15:31 +00001425 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001426 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001427 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001428
Fangrui Song050229d2018-11-24 00:14:31 +00001429 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1430 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001431}
1432
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001433/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001434/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001435bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001436 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001437 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001438 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001439
Douglas Gregor3545ff42009-09-21 16:56:56 +00001440 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1441}
1442
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001443/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001444bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001445 return isa<EnumDecl>(ND);
1446}
1447
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001448/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001449bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001450 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001451 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001452 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001453
1454 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001455 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1456 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1457 RD->getTagKind() == TTK_Interface;
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 union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001463bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001464 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001465 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001466 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001467
Fangrui Song050229d2018-11-24 00:14:31 +00001468 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001469 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001470
Douglas Gregor3545ff42009-09-21 16:56:56 +00001471 return false;
1472}
1473
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001474/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001475bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001476 return isa<NamespaceDecl>(ND);
1477}
1478
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001479/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001480/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001481bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001482 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001483}
1484
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001485/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001486bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001487 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001488 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001489}
1490
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001491/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001492/// "." or "->". Only value declarations, nested name specifiers, and
1493/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001494bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001495 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001496 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001497 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001498}
1499
Douglas Gregora817a192010-05-27 23:06:34 +00001500static bool isObjCReceiverType(ASTContext &C, QualType T) {
1501 T = C.getCanonicalType(T);
1502 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001503 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001504 case Type::ObjCInterface:
1505 case Type::ObjCObjectPointer:
1506 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001507
Douglas Gregora817a192010-05-27 23:06:34 +00001508 case Type::Builtin:
1509 switch (cast<BuiltinType>(T)->getKind()) {
1510 case BuiltinType::ObjCId:
1511 case BuiltinType::ObjCClass:
1512 case BuiltinType::ObjCSel:
1513 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001514
Douglas Gregora817a192010-05-27 23:06:34 +00001515 default:
1516 break;
1517 }
1518 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001519
Douglas Gregora817a192010-05-27 23:06:34 +00001520 default:
1521 break;
1522 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001523
David Blaikiebbafb8a2012-03-11 07:00:24 +00001524 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001525 return false;
1526
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001527 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001528 // particular class type has any conversions to Objective-C types. For now,
1529 // just accept all class types.
1530 return T->isDependentType() || T->isRecordType();
1531}
1532
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001533bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001534 QualType T = getDeclUsageType(SemaRef.Context, ND);
1535 if (T.isNull())
1536 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001537
Douglas Gregora817a192010-05-27 23:06:34 +00001538 T = SemaRef.Context.getBaseElementType(T);
1539 return isObjCReceiverType(SemaRef.Context, T);
1540}
1541
Fangrui Song050229d2018-11-24 00:14:31 +00001542bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1543 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001544 if (IsObjCMessageReceiver(ND))
1545 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001546
Fangrui Song050229d2018-11-24 00:14:31 +00001547 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001548 if (!Var)
1549 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001550
Douglas Gregord8c61782012-02-15 15:34:24 +00001551 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1552}
1553
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001554bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001555 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1556 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001557 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001558
Douglas Gregor68762e72010-08-23 21:17:50 +00001559 QualType T = getDeclUsageType(SemaRef.Context, ND);
1560 if (T.isNull())
1561 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001562
Douglas Gregor68762e72010-08-23 21:17:50 +00001563 T = SemaRef.Context.getBaseElementType(T);
1564 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001565 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001566 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001567}
Douglas Gregora817a192010-05-27 23:06:34 +00001568
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001569bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001570 return false;
1571}
1572
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001573/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001574/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001575bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001576 return isa<ObjCIvarDecl>(ND);
1577}
1578
Douglas Gregorc580c522010-01-14 01:09:38 +00001579namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001580
Fangrui Song050229d2018-11-24 00:14:31 +00001581/// Visible declaration consumer that adds a code-completion result
1582/// for each visible declaration.
1583class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1584 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001585 DeclContext *InitialLookupCtx;
1586 // NamingClass and BaseType are used for access-checking. See
1587 // Sema::IsSimplyAccessible for details.
1588 CXXRecordDecl *NamingClass;
1589 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001590 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001591
Fangrui Song050229d2018-11-24 00:14:31 +00001592public:
1593 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001594 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1595 QualType BaseType = QualType(),
1596 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1597 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1598 FixIts(std::move(FixIts)) {
1599 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1600 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1601 if (BaseType.isNull()) {
1602 auto ThisType = Results.getSema().getCurrentThisType();
1603 if (!ThisType.isNull()) {
1604 assert(ThisType->isPointerType());
1605 BaseType = ThisType->getPointeeType();
1606 if (!NamingClass)
1607 NamingClass = BaseType->getAsCXXRecordDecl();
1608 }
1609 }
1610 this->BaseType = BaseType;
1611 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001612
Fangrui Song050229d2018-11-24 00:14:31 +00001613 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1614 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001615 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001616 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001617 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001618 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001619
Fangrui Song050229d2018-11-24 00:14:31 +00001620 void EnteredContext(DeclContext *Ctx) override {
1621 Results.addVisitedContext(Ctx);
1622 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001623
1624private:
1625 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1626 // Naming class to use for access check. In most cases it was provided
1627 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1628 // for unqualified lookup we fallback to the \p Ctx in which we found the
1629 // member.
1630 auto *NamingClass = this->NamingClass;
1631 QualType BaseType = this->BaseType;
1632 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1633 if (!NamingClass)
1634 NamingClass = Cls;
1635 // When we emulate implicit 'this->' in an unqualified lookup, we might
1636 // end up with an invalid naming class. In that case, we avoid emulating
1637 // 'this->' qualifier to satisfy preconditions of the access checking.
1638 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1639 !NamingClass->isDerivedFrom(Cls)) {
1640 NamingClass = Cls;
1641 BaseType = QualType();
1642 }
1643 } else {
1644 // The decl was found outside the C++ class, so only ObjC access checks
1645 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1646 // out.
1647 NamingClass = nullptr;
1648 BaseType = QualType();
1649 }
1650 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1651 }
Fangrui Song050229d2018-11-24 00:14:31 +00001652};
1653} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001654
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001655/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001656static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001657 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001658 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001659 Results.AddResult(Result("short", CCP_Type));
1660 Results.AddResult(Result("long", CCP_Type));
1661 Results.AddResult(Result("signed", CCP_Type));
1662 Results.AddResult(Result("unsigned", CCP_Type));
1663 Results.AddResult(Result("void", CCP_Type));
1664 Results.AddResult(Result("char", CCP_Type));
1665 Results.AddResult(Result("int", CCP_Type));
1666 Results.AddResult(Result("float", CCP_Type));
1667 Results.AddResult(Result("double", CCP_Type));
1668 Results.AddResult(Result("enum", CCP_Type));
1669 Results.AddResult(Result("struct", CCP_Type));
1670 Results.AddResult(Result("union", CCP_Type));
1671 Results.AddResult(Result("const", CCP_Type));
1672 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001673
Douglas Gregor3545ff42009-09-21 16:56:56 +00001674 if (LangOpts.C99) {
1675 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001676 Results.AddResult(Result("_Complex", CCP_Type));
1677 Results.AddResult(Result("_Imaginary", CCP_Type));
1678 Results.AddResult(Result("_Bool", CCP_Type));
1679 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001680 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001681
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001682 CodeCompletionBuilder Builder(Results.getAllocator(),
1683 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001684 if (LangOpts.CPlusPlus) {
1685 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001686 Results.AddResult(
1687 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001688 Results.AddResult(Result("class", CCP_Type));
1689 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001690
Douglas Gregorf4c33342010-05-28 00:22:41 +00001691 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001692 Builder.AddTypedTextChunk("typename");
1693 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1694 Builder.AddPlaceholderChunk("qualifier");
1695 Builder.AddTextChunk("::");
1696 Builder.AddPlaceholderChunk("name");
1697 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001698
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001699 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001700 Results.AddResult(Result("auto", CCP_Type));
1701 Results.AddResult(Result("char16_t", CCP_Type));
1702 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001703
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001704 Builder.AddTypedTextChunk("decltype");
1705 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1706 Builder.AddPlaceholderChunk("expression");
1707 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1708 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001709 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001710 } else
1711 Results.AddResult(Result("__auto_type", CCP_Type));
1712
Richard Smith7b301e22018-05-24 21:51:52 +00001713 // GNU keywords
1714 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001715 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001716 // Results.AddResult(Result("_Decimal32"));
1717 // Results.AddResult(Result("_Decimal64"));
1718 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001719
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001720 Builder.AddTypedTextChunk("typeof");
1721 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1722 Builder.AddPlaceholderChunk("expression");
1723 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001724
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001725 Builder.AddTypedTextChunk("typeof");
1726 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1727 Builder.AddPlaceholderChunk("type");
1728 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1729 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001730 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001731
1732 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001733 Results.AddResult(Result("_Nonnull", CCP_Type));
1734 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1735 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001736}
1737
John McCallfaf5fb42010-08-26 23:41:50 +00001738static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001739 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001740 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001741 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001742 // Note: we don't suggest either "auto" or "register", because both
1743 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1744 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001745 Results.AddResult(Result("extern"));
1746 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001747
1748 if (LangOpts.CPlusPlus11) {
1749 CodeCompletionAllocator &Allocator = Results.getAllocator();
1750 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1751
1752 // alignas
1753 Builder.AddTypedTextChunk("alignas");
1754 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1755 Builder.AddPlaceholderChunk("expression");
1756 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1757 Results.AddResult(Result(Builder.TakeString()));
1758
1759 Results.AddResult(Result("constexpr"));
1760 Results.AddResult(Result("thread_local"));
1761 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001762}
1763
John McCallfaf5fb42010-08-26 23:41:50 +00001764static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001765 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001766 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001767 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001768 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001769 case Sema::PCC_Class:
1770 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001771 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001772 Results.AddResult(Result("explicit"));
1773 Results.AddResult(Result("friend"));
1774 Results.AddResult(Result("mutable"));
1775 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001776 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001777 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001778
John McCallfaf5fb42010-08-26 23:41:50 +00001779 case Sema::PCC_ObjCInterface:
1780 case Sema::PCC_ObjCImplementation:
1781 case Sema::PCC_Namespace:
1782 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001783 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001784 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001785 break;
1786
John McCallfaf5fb42010-08-26 23:41:50 +00001787 case Sema::PCC_ObjCInstanceVariableList:
1788 case Sema::PCC_Expression:
1789 case Sema::PCC_Statement:
1790 case Sema::PCC_ForInit:
1791 case Sema::PCC_Condition:
1792 case Sema::PCC_RecoveryInFunction:
1793 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001794 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001795 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001796 break;
1797 }
1798}
1799
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001800static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1801static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1802static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001803 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001804static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001805 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001806static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001807 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001808static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001809
Douglas Gregorf4c33342010-05-28 00:22:41 +00001810static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001811 CodeCompletionBuilder Builder(Results.getAllocator(),
1812 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001813 Builder.AddTypedTextChunk("typedef");
1814 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1815 Builder.AddPlaceholderChunk("type");
1816 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1817 Builder.AddPlaceholderChunk("name");
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001818 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001819 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001820}
1821
John McCallfaf5fb42010-08-26 23:41:50 +00001822static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001823 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001824 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001825 case Sema::PCC_Namespace:
1826 case Sema::PCC_Class:
1827 case Sema::PCC_ObjCInstanceVariableList:
1828 case Sema::PCC_Template:
1829 case Sema::PCC_MemberTemplate:
1830 case Sema::PCC_Statement:
1831 case Sema::PCC_RecoveryInFunction:
1832 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001833 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001834 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001835 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001836
John McCallfaf5fb42010-08-26 23:41:50 +00001837 case Sema::PCC_Expression:
1838 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001839 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001840
Douglas Gregor5e35d592010-09-14 23:59:36 +00001841 case Sema::PCC_ObjCInterface:
1842 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001843 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001844
John McCallfaf5fb42010-08-26 23:41:50 +00001845 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001846 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001847 }
David Blaikie8a40f702012-01-17 06:56:22 +00001848
1849 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001850}
1851
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001852static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1853 const Preprocessor &PP) {
1854 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001855 Policy.AnonymousTagLocations = false;
1856 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001857 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001858 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001859 return Policy;
1860}
1861
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001862/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001863static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1864 return getCompletionPrintingPolicy(S.Context, S.PP);
1865}
1866
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001867/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001868/// that has the appropriate lifetime for code completion.
1869///
1870/// This routine provides a fast path where we provide constant strings for
1871/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001872static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001873 const PrintingPolicy &Policy,
1874 CodeCompletionAllocator &Allocator) {
1875 if (!T.getLocalQualifiers()) {
1876 // Built-in type names are constant strings.
1877 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001878 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001879
Douglas Gregore5c79d52011-10-18 21:20:17 +00001880 // Anonymous tag types are constant strings.
1881 if (const TagType *TagT = dyn_cast<TagType>(T))
1882 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001883 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001884 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001885 case TTK_Struct:
1886 return "struct <anonymous>";
1887 case TTK_Interface:
1888 return "__interface <anonymous>";
1889 case TTK_Class:
1890 return "class <anonymous>";
1891 case TTK_Union:
1892 return "union <anonymous>";
1893 case TTK_Enum:
1894 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001895 }
1896 }
1897 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001898
Douglas Gregore5c79d52011-10-18 21:20:17 +00001899 // Slow path: format the type as a string.
1900 std::string Result;
1901 T.getAsStringInternal(Result, Policy);
1902 return Allocator.CopyString(Result);
1903}
1904
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001905/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001906static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1907 QualType ThisTy = S.getCurrentThisType();
1908 if (ThisTy.isNull())
1909 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001910
Douglas Gregord8c61782012-02-15 15:34:24 +00001911 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001912 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001913 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001914 Builder.AddResultTypeChunk(
1915 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001916 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001917 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001918}
1919
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001920static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1921 ResultBuilder &Results,
1922 const LangOptions &LangOpts) {
1923 if (!LangOpts.CPlusPlus11)
1924 return;
1925
1926 Builder.AddTypedTextChunk("static_assert");
1927 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1928 Builder.AddPlaceholderChunk("expression");
1929 Builder.AddChunk(CodeCompletionString::CK_Comma);
1930 Builder.AddPlaceholderChunk("message");
1931 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001932 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001933 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1934}
1935
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001936static void AddOverrideResults(ResultBuilder &Results,
1937 const CodeCompletionContext &CCContext,
1938 CodeCompletionBuilder &Builder) {
1939 Sema &S = Results.getSema();
1940 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1941 // If not inside a class/struct/union return empty.
1942 if (!CR)
1943 return;
1944 // First store overrides within current class.
1945 // These are stored by name to make querying fast in the later step.
1946 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1947 for (auto *Method : CR->methods()) {
1948 if (!Method->isVirtual() || !Method->getIdentifier())
1949 continue;
1950 Overrides[Method->getName()].push_back(Method);
1951 }
1952
1953 for (const auto &Base : CR->bases()) {
1954 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1955 if (!BR)
1956 continue;
1957 for (auto *Method : BR->methods()) {
1958 if (!Method->isVirtual() || !Method->getIdentifier())
1959 continue;
1960 const auto it = Overrides.find(Method->getName());
1961 bool IsOverriden = false;
1962 if (it != Overrides.end()) {
1963 for (auto *MD : it->second) {
1964 // If the method in current body is not an overload of this virtual
1965 // function, then it overrides this one.
1966 if (!S.IsOverload(MD, Method, false)) {
1967 IsOverriden = true;
1968 break;
1969 }
1970 }
1971 }
1972 if (!IsOverriden) {
1973 // Generates a new CodeCompletionResult by taking this function and
1974 // converting it into an override declaration with only one chunk in the
1975 // final CodeCompletionString as a TypedTextChunk.
1976 std::string OverrideSignature;
1977 llvm::raw_string_ostream OS(OverrideSignature);
1978 CodeCompletionResult CCR(Method, 0);
1979 PrintingPolicy Policy =
1980 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1981 auto *CCS = CCR.createCodeCompletionStringForOverride(
1982 S.getPreprocessor(), S.getASTContext(), Builder,
1983 /*IncludeBriefComments=*/false, CCContext, Policy);
1984 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1985 }
1986 }
1987 }
1988}
1989
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001990/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001991static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1992 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001993 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001994 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001995
John McCall276321a2010-08-25 06:19:51 +00001996 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001997 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001998 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001999 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002000 if (Results.includeCodePatterns()) {
2001 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002002 Builder.AddTypedTextChunk("namespace");
2003 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2004 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002005 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002006 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002007 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002008 Builder.AddPlaceholderChunk("declarations");
2009 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2010 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2011 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002012 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002013
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002014 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002015 Builder.AddTypedTextChunk("namespace");
2016 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2017 Builder.AddPlaceholderChunk("name");
2018 Builder.AddChunk(CodeCompletionString::CK_Equal);
2019 Builder.AddPlaceholderChunk("namespace");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002020 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002021 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002022
2023 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002024 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002025 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2026 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002027 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002028 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002029
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002030 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002031 Builder.AddTypedTextChunk("asm");
2032 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2033 Builder.AddPlaceholderChunk("string-literal");
2034 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2035 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002036
Douglas Gregorf4c33342010-05-28 00:22:41 +00002037 if (Results.includeCodePatterns()) {
2038 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002039 Builder.AddTypedTextChunk("template");
2040 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2041 Builder.AddPlaceholderChunk("declaration");
2042 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002043 } else {
2044 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002045 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002046 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002047
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002048 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002049 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002050
Douglas Gregorf4c33342010-05-28 00:22:41 +00002051 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002052 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002053
John McCallfaf5fb42010-08-26 23:41:50 +00002054 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002055 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002056 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002057 Builder.AddTypedTextChunk("using");
2058 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2059 Builder.AddPlaceholderChunk("qualifier");
2060 Builder.AddTextChunk("::");
2061 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002062 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002063 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002064
Douglas Gregorf4c33342010-05-28 00:22:41 +00002065 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002066 if (SemaRef.CurContext->isDependentContext()) {
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002067 Builder.AddTypedTextChunk("using typename");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002068 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2069 Builder.AddPlaceholderChunk("qualifier");
2070 Builder.AddTextChunk("::");
2071 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002072 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002073 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002074 }
2075
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002076 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
2077
John McCallfaf5fb42010-08-26 23:41:50 +00002078 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002079 AddTypedefResult(Results);
2080
Erik Verbruggen6524c052017-10-24 13:46:58 +00002081 bool IsNotInheritanceScope =
2082 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002083 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002084 Builder.AddTypedTextChunk("public");
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()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002088
2089 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002090 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002091 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002092 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002093 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002094
2095 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002096 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002097 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002098 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002099 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002100
2101 // FIXME: This adds override results only if we are at the first word of
2102 // the declaration/definition. Also call this from other sides to have
2103 // more use-cases.
2104 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
2105 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002106 }
2107 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002108 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002109
John McCallfaf5fb42010-08-26 23:41:50 +00002110 case Sema::PCC_Template:
2111 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002112 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002113 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002114 Builder.AddTypedTextChunk("template");
2115 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2116 Builder.AddPlaceholderChunk("parameters");
2117 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2118 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002119 } else {
2120 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002121 }
2122
David Blaikiebbafb8a2012-03-11 07:00:24 +00002123 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2124 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002125 break;
2126
John McCallfaf5fb42010-08-26 23:41:50 +00002127 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002128 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2129 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2130 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002131 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002132
John McCallfaf5fb42010-08-26 23:41:50 +00002133 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002134 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2135 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2136 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002137 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002138
John McCallfaf5fb42010-08-26 23:41:50 +00002139 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002140 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002141 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002142
John McCallfaf5fb42010-08-26 23:41:50 +00002143 case Sema::PCC_RecoveryInFunction:
2144 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002145 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002146
David Blaikiebbafb8a2012-03-11 07:00:24 +00002147 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2148 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002149 Builder.AddTypedTextChunk("try");
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);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002156 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002157 Builder.AddTextChunk("catch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002158 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002159 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2160 Builder.AddPlaceholderChunk("declaration");
2161 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002162 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002163 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002164 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002165 Builder.AddPlaceholderChunk("statements");
2166 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2167 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2168 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002169 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002170 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002171 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002172
Douglas Gregorf64acca2010-05-25 21:41:55 +00002173 if (Results.includeCodePatterns()) {
2174 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002175 Builder.AddTypedTextChunk("if");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002176 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002177 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002178 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002179 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002180 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002181 Builder.AddPlaceholderChunk("expression");
2182 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002183 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002184 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002185 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002186 Builder.AddPlaceholderChunk("statements");
2187 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2188 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2189 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002190
Douglas Gregorf64acca2010-05-25 21:41:55 +00002191 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002192 Builder.AddTypedTextChunk("switch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002193 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002194 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002195 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002196 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002197 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002198 Builder.AddPlaceholderChunk("expression");
2199 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002200 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002201 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2202 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002203 Builder.AddPlaceholderChunk("cases");
2204 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002205 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2206 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002207 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002208
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002209 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002210 if (SemaRef.getCurFunction() &&
2211 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002212 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002213 Builder.AddTypedTextChunk("case");
2214 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2215 Builder.AddPlaceholderChunk("expression");
2216 Builder.AddChunk(CodeCompletionString::CK_Colon);
2217 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002218
2219 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002220 Builder.AddTypedTextChunk("default");
2221 Builder.AddChunk(CodeCompletionString::CK_Colon);
2222 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002223 }
2224
Douglas Gregorf64acca2010-05-25 21:41:55 +00002225 if (Results.includeCodePatterns()) {
2226 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002227 Builder.AddTypedTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002228 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002229 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002230 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002231 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002232 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002233 Builder.AddPlaceholderChunk("expression");
2234 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002235 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002236 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002237 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002238 Builder.AddPlaceholderChunk("statements");
2239 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2240 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2241 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002242
2243 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002244 Builder.AddTypedTextChunk("do");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002245 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002246 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002247 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002248 Builder.AddPlaceholderChunk("statements");
2249 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2250 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2251 Builder.AddTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002252 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002253 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2254 Builder.AddPlaceholderChunk("expression");
2255 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2256 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002257
Douglas Gregorf64acca2010-05-25 21:41:55 +00002258 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002259 Builder.AddTypedTextChunk("for");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002260 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002261 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002262 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002263 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002264 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002265 Builder.AddPlaceholderChunk("init-expression");
2266 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002267 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002268 Builder.AddPlaceholderChunk("condition");
2269 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002270 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002271 Builder.AddPlaceholderChunk("inc-expression");
2272 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002273 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002274 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2275 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2276 Builder.AddPlaceholderChunk("statements");
2277 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2278 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2279 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002280 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002281
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002282 if (S->getContinueParent()) {
2283 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002284 Builder.AddTypedTextChunk("continue");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002285 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002286 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002287 }
2288
2289 if (S->getBreakParent()) {
2290 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002291 Builder.AddTypedTextChunk("break");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002292 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002293 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002294 }
2295
Ilya Biryukov32497f52019-05-27 09:52:09 +00002296 // "return expression ;" or "return ;", depending on the return type.
2297 QualType ReturnType;
Fangrui Song050229d2018-11-24 00:14:31 +00002298 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002299 ReturnType = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002300 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002301 ReturnType = Method->getReturnType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002302 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002303 !SemaRef.getCurBlock()->ReturnType.isNull())
Ilya Biryukov32497f52019-05-27 09:52:09 +00002304 ReturnType = SemaRef.getCurBlock()->ReturnType;;
2305 if (ReturnType.isNull() || ReturnType->isVoidType()) {
2306 Builder.AddTypedTextChunk("return");
2307 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2308 Results.AddResult(Result(Builder.TakeString()));
2309 } else {
2310 assert(!ReturnType.isNull());
2311 // "return expression ;"
2312 Builder.AddTypedTextChunk("return");
2313 Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002314 Builder.AddPlaceholderChunk("expression");
Ilya Biryukov32497f52019-05-27 09:52:09 +00002315 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2316 Results.AddResult(Result(Builder.TakeString()));
2317 // When boolean, also add 'return true;' and 'return false;'.
2318 if (ReturnType->isBooleanType()) {
2319 Builder.AddTypedTextChunk("return true");
2320 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2321 Results.AddResult(Result(Builder.TakeString()));
2322
2323 Builder.AddTypedTextChunk("return false");
2324 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2325 Results.AddResult(Result(Builder.TakeString()));
2326 }
Douglas Gregor44272ca2010-02-18 04:06:48 +00002327 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002328
Douglas Gregorf4c33342010-05-28 00:22:41 +00002329 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002330 Builder.AddTypedTextChunk("goto");
2331 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2332 Builder.AddPlaceholderChunk("label");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002333 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002334 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002335
Douglas Gregorf4c33342010-05-28 00:22:41 +00002336 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002337 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002338 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2339 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002340 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002341 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002342
2343 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002344 }
Fangrui Song050229d2018-11-24 00:14:31 +00002345 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002346
2347 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002348 case Sema::PCC_ForInit:
2349 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002350 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002351 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002352 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002353
Douglas Gregor5e35d592010-09-14 23:59:36 +00002354 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002355 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002356 CCC == Sema::PCC_ParenthesizedExpression) {
2357 // (__bridge <type>)<expression>
2358 Builder.AddTypedTextChunk("__bridge");
2359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2360 Builder.AddPlaceholderChunk("type");
2361 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2362 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002363 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002364
2365 // (__bridge_transfer <Objective-C type>)<expression>
2366 Builder.AddTypedTextChunk("__bridge_transfer");
2367 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2368 Builder.AddPlaceholderChunk("Objective-C type");
2369 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2370 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002371 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002372
2373 // (__bridge_retained <CF type>)<expression>
2374 Builder.AddTypedTextChunk("__bridge_retained");
2375 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2376 Builder.AddPlaceholderChunk("CF type");
2377 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2378 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002379 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002380 }
2381 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002382 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002383
John McCallfaf5fb42010-08-26 23:41:50 +00002384 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002385 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002386 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002387 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002388
Douglas Gregore5c79d52011-10-18 21:20:17 +00002389 // true
2390 Builder.AddResultTypeChunk("bool");
2391 Builder.AddTypedTextChunk("true");
2392 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002393
Douglas Gregore5c79d52011-10-18 21:20:17 +00002394 // false
2395 Builder.AddResultTypeChunk("bool");
2396 Builder.AddTypedTextChunk("false");
2397 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002398
David Blaikiebbafb8a2012-03-11 07:00:24 +00002399 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002400 // dynamic_cast < type-id > ( expression )
2401 Builder.AddTypedTextChunk("dynamic_cast");
2402 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2403 Builder.AddPlaceholderChunk("type");
2404 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2406 Builder.AddPlaceholderChunk("expression");
2407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002408 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002409 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002410
Douglas Gregorf4c33342010-05-28 00:22:41 +00002411 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002412 Builder.AddTypedTextChunk("static_cast");
2413 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2414 Builder.AddPlaceholderChunk("type");
2415 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2416 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2417 Builder.AddPlaceholderChunk("expression");
2418 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002419 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002420
Douglas Gregorf4c33342010-05-28 00:22:41 +00002421 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002422 Builder.AddTypedTextChunk("reinterpret_cast");
2423 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2424 Builder.AddPlaceholderChunk("type");
2425 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2426 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2427 Builder.AddPlaceholderChunk("expression");
2428 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002429 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002430
Douglas Gregorf4c33342010-05-28 00:22:41 +00002431 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002432 Builder.AddTypedTextChunk("const_cast");
2433 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2434 Builder.AddPlaceholderChunk("type");
2435 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2436 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2437 Builder.AddPlaceholderChunk("expression");
2438 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002439 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002440
David Blaikiebbafb8a2012-03-11 07:00:24 +00002441 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002442 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002443 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002444 Builder.AddTypedTextChunk("typeid");
2445 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2446 Builder.AddPlaceholderChunk("expression-or-type");
2447 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002448 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002449 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002450
Douglas Gregorf4c33342010-05-28 00:22:41 +00002451 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002452 Builder.AddTypedTextChunk("new");
2453 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2454 Builder.AddPlaceholderChunk("type");
2455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2456 Builder.AddPlaceholderChunk("expressions");
2457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002458 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002459
Douglas Gregorf4c33342010-05-28 00:22:41 +00002460 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002461 Builder.AddTypedTextChunk("new");
2462 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2463 Builder.AddPlaceholderChunk("type");
2464 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2465 Builder.AddPlaceholderChunk("size");
2466 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2467 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2468 Builder.AddPlaceholderChunk("expressions");
2469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002470 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002471
Douglas Gregorf4c33342010-05-28 00:22:41 +00002472 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002473 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002474 Builder.AddTypedTextChunk("delete");
2475 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2476 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002477 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002478
Douglas Gregorf4c33342010-05-28 00:22:41 +00002479 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002480 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002481 Builder.AddTypedTextChunk("delete");
2482 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2483 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2484 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2485 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2486 Builder.AddPlaceholderChunk("expression");
2487 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002488
David Blaikiebbafb8a2012-03-11 07:00:24 +00002489 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002490 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002491 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002492 Builder.AddTypedTextChunk("throw");
2493 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2494 Builder.AddPlaceholderChunk("expression");
2495 Results.AddResult(Result(Builder.TakeString()));
2496 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002497
Douglas Gregora2db7932010-05-26 22:00:08 +00002498 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002499
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002500 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002501 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002502 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002503 Builder.AddTypedTextChunk("nullptr");
2504 Results.AddResult(Result(Builder.TakeString()));
2505
2506 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002507 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002508 Builder.AddTypedTextChunk("alignof");
2509 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2510 Builder.AddPlaceholderChunk("type");
2511 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2512 Results.AddResult(Result(Builder.TakeString()));
2513
2514 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002515 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002516 Builder.AddTypedTextChunk("noexcept");
2517 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2518 Builder.AddPlaceholderChunk("expression");
2519 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2520 Results.AddResult(Result(Builder.TakeString()));
2521
2522 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002523 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002524 Builder.AddTypedTextChunk("sizeof...");
2525 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2526 Builder.AddPlaceholderChunk("parameter-pack");
2527 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2528 Results.AddResult(Result(Builder.TakeString()));
2529 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002530 }
2531
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002532 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002533 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002534 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2535 // The interface can be NULL.
2536 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002537 if (ID->getSuperClass()) {
2538 std::string SuperType;
2539 SuperType = ID->getSuperClass()->getNameAsString();
2540 if (Method->isInstanceMethod())
2541 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002542
Douglas Gregore5c79d52011-10-18 21:20:17 +00002543 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2544 Builder.AddTypedTextChunk("super");
2545 Results.AddResult(Result(Builder.TakeString()));
2546 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002547 }
2548
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002549 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002550 }
2551
Jordan Rose58d54722012-06-30 21:33:57 +00002552 if (SemaRef.getLangOpts().C11) {
2553 // _Alignof
2554 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002555 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002556 Builder.AddTypedTextChunk("alignof");
2557 else
2558 Builder.AddTypedTextChunk("_Alignof");
2559 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2560 Builder.AddPlaceholderChunk("type");
2561 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2562 Results.AddResult(Result(Builder.TakeString()));
2563 }
2564
Douglas Gregorf4c33342010-05-28 00:22:41 +00002565 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002566 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002567 Builder.AddTypedTextChunk("sizeof");
2568 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2569 Builder.AddPlaceholderChunk("expression-or-type");
2570 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2571 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002572 break;
2573 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002574
John McCallfaf5fb42010-08-26 23:41:50 +00002575 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002576 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002577 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002578 }
2579
David Blaikiebbafb8a2012-03-11 07:00:24 +00002580 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2581 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002582
David Blaikiebbafb8a2012-03-11 07:00:24 +00002583 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002584 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002585}
2586
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002587/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002588/// type chunk.
2589static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002590 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002591 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002592 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002593 if (!ND)
2594 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002595
2596 // Skip constructors and conversion functions, which have their return types
2597 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002598 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002599 return;
2600
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002601 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002602 QualType T;
2603 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002604 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002605 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002606 if (!BaseType.isNull())
2607 T = Method->getSendResultType(BaseType);
2608 else
2609 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002610 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002611 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002612 T = clang::TypeName::getFullyQualifiedType(T, Context);
2613 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002614 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002615 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002616 if (!BaseType.isNull())
2617 T = Ivar->getUsageType(BaseType);
2618 else
2619 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002620 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002621 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002622 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002623 if (!BaseType.isNull())
2624 T = Property->getUsageType(BaseType);
2625 else
2626 T = Property->getType();
2627 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002628
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002629 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2630 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002631
Fangrui Song050229d2018-11-24 00:14:31 +00002632 Result.AddResultTypeChunk(
2633 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002634}
2635
Richard Smith20e883e2015-04-29 23:20:19 +00002636static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002637 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002638 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002639 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2640 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002641 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002642 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002643 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002644 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002645 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002646 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002647 }
2648}
2649
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002650static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002651 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002652 std::string Result;
2653 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002654 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002655 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002656 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002657 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002658 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002659 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002660 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002661 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002662 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002663 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002664 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002665 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2666 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2667 switch (*nullability) {
2668 case NullabilityKind::NonNull:
2669 Result += "nonnull ";
2670 break;
2671
2672 case NullabilityKind::Nullable:
2673 Result += "nullable ";
2674 break;
2675
2676 case NullabilityKind::Unspecified:
2677 Result += "null_unspecified ";
2678 break;
2679 }
2680 }
2681 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002682 return Result;
2683}
2684
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002685/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002686/// block placeholder.
2687///
2688/// This function ignores things like typedefs and qualifiers in order to
2689/// present the most relevant and accurate block placeholders in code completion
2690/// results.
2691static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2692 FunctionTypeLoc &Block,
2693 FunctionProtoTypeLoc &BlockProto,
2694 bool SuppressBlock = false) {
2695 if (!TSInfo)
2696 return;
2697 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2698 while (true) {
2699 // Look through typedefs.
2700 if (!SuppressBlock) {
2701 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2702 if (TypeSourceInfo *InnerTSInfo =
2703 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2704 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2705 continue;
2706 }
2707 }
2708
2709 // Look through qualified types
2710 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2711 TL = QualifiedTL.getUnqualifiedLoc();
2712 continue;
2713 }
2714
2715 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2716 TL = AttrTL.getModifiedLoc();
2717 continue;
2718 }
2719 }
2720
2721 // Try to get the function prototype behind the block pointer type,
2722 // then we're done.
2723 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2724 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2725 Block = TL.getAs<FunctionTypeLoc>();
2726 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2727 }
2728 break;
2729 }
2730}
2731
Alex Lorenz920ae142016-10-18 10:38:58 +00002732static std::string
2733formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2734 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002735 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002736 bool SuppressBlock = false,
2737 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2738
Fangrui Song050229d2018-11-24 00:14:31 +00002739static std::string
2740FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2741 bool SuppressName = false, bool SuppressBlock = false,
2742 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Sam McCallbc7ff892019-04-04 11:34:18 +00002743 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.
2744 // It would be better to pass in the param Type, which is usually avaliable.
2745 // But this case is rare, so just pretend we fell back to int as elsewhere.
2746 if (!Param)
2747 return "int";
Douglas Gregore90dd002010-08-24 16:15:59 +00002748 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2749 if (Param->getType()->isDependentType() ||
2750 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002751 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002752 // containing that parameter's type.
2753 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002754
Douglas Gregor981a0c42010-08-29 19:47:46 +00002755 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002756 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002757
Douglas Gregor86b42682015-06-19 18:27:52 +00002758 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002759 if (ObjCSubsts)
2760 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2761 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002762 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002763 Result =
2764 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002765 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002766 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002767 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002768 } else {
2769 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002770 }
2771 return Result;
2772 }
Alex Lorenza1951202016-10-18 10:35:27 +00002773
Douglas Gregore90dd002010-08-24 16:15:59 +00002774 // The argument for a block pointer parameter is a block literal with
2775 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002776 FunctionTypeLoc Block;
2777 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002778 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2779 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002780 // Try to retrieve the block type information from the property if this is a
2781 // parameter in a setter.
2782 if (!Block && ObjCMethodParam &&
2783 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2784 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2785 ->findPropertyDecl(/*CheckOverrides=*/false))
2786 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2787 SuppressBlock);
2788 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002789
2790 if (!Block) {
2791 // We were unable to find a FunctionProtoTypeLoc with parameter names
2792 // for the block; just use the parameter type as a placeholder.
2793 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002794 if (!ObjCMethodParam && Param->getIdentifier())
2795 Result = Param->getIdentifier()->getName();
2796
Douglas Gregor86b42682015-06-19 18:27:52 +00002797 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002798
Douglas Gregore90dd002010-08-24 16:15:59 +00002799 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002800 Result = Type.getAsString(Policy);
2801 std::string Quals =
2802 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2803 if (!Quals.empty())
2804 Result = "(" + Quals + " " + Result + ")";
2805 if (Result.back() != ')')
2806 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002807 if (Param->getIdentifier())
2808 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002809 } else {
2810 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002811 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002812
Douglas Gregore90dd002010-08-24 16:15:59 +00002813 return Result;
2814 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002815
Douglas Gregore90dd002010-08-24 16:15:59 +00002816 // We have the function prototype behind the block pointer type, as it was
2817 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002818 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2819 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002820 ObjCSubsts);
2821}
2822
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002823/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002824/// declaration.
2825///
2826/// \param BlockDecl A declaration with an Objective-C block type.
2827///
2828/// \param Block The most relevant type location for that block type.
2829///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002830/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002831/// declaration is included in the resulting string.
2832static std::string
2833formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2834 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002835 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002836 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002837 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002838 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002839 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002840 ResultType =
2841 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2842 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002843 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002844 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002845
2846 // Format the parameter list.
2847 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002848 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002849 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002850 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002851 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002852 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002853 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002854 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002855 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002856 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002857 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002858 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002859 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002860 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002861
David Blaikie6adc78e2013-02-18 22:06:02 +00002862 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002863 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002864 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002865 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002866 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002867
Douglas Gregord793e7c2011-10-18 04:23:19 +00002868 if (SuppressBlock) {
2869 // Format as a parameter.
2870 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002871 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002872 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002873 Result += ")";
2874 Result += Params;
2875 } else {
2876 // Format as a block literal argument.
2877 Result = '^' + Result;
2878 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002879
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002880 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002881 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002882 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002883
Douglas Gregore90dd002010-08-24 16:15:59 +00002884 return Result;
2885}
2886
Erik Verbruggen11338c52017-07-19 10:45:40 +00002887static std::string GetDefaultValueString(const ParmVarDecl *Param,
2888 const SourceManager &SM,
2889 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002890 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002891 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2892 bool Invalid = CharSrcRange.isInvalid();
2893 if (Invalid)
2894 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002895 StringRef srcText =
2896 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002897 if (Invalid)
2898 return "";
2899
2900 if (srcText.empty() || srcText == "=") {
2901 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002902 // This happens if the code is incorrect (for example class is forward
2903 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002904 return "";
2905 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002906 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002907 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2908 // this value always has (or always does not have) '=' in front of it
2909 if (DefValue.at(0) != '=') {
2910 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002911 // Lexer returns built-in types values without '=' and user-defined types
2912 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002913 return " = " + DefValue;
2914 }
2915 return " " + DefValue;
2916}
2917
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002918/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002919static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002920 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002921 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002922 CodeCompletionBuilder &Result,
2923 unsigned Start = 0,
2924 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002925 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002926
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002927 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002928 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002929
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002930 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002931 // When we see an optional default argument, put that argument and
2932 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002933 CodeCompletionBuilder Opt(Result.getAllocator(),
2934 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002935 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002936 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002937 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002938 Result.AddOptionalChunk(Opt.TakeString());
2939 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002940 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002941
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002942 if (FirstParameter)
2943 FirstParameter = false;
2944 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002945 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002946
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002947 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002948
Douglas Gregor3545ff42009-09-21 16:56:56 +00002949 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002950 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002951 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002952 PlaceholderStr +=
2953 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002954
Douglas Gregor400f5972010-08-31 05:13:43 +00002955 if (Function->isVariadic() && P == N - 1)
2956 PlaceholderStr += ", ...";
2957
Douglas Gregor3545ff42009-09-21 16:56:56 +00002958 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002959 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002960 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002961 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002962
Fangrui Song050229d2018-11-24 00:14:31 +00002963 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002964 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002965 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002966 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002967
Richard Smith20e883e2015-04-29 23:20:19 +00002968 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002969 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002970}
2971
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002972/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002973static void AddTemplateParameterChunks(
2974 ASTContext &Context, const PrintingPolicy &Policy,
2975 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2976 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002977 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002978
2979 // Prefer to take the template parameter names from the first declaration of
2980 // the template.
2981 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2982
Douglas Gregor3545ff42009-09-21 16:56:56 +00002983 TemplateParameterList *Params = Template->getTemplateParameters();
2984 TemplateParameterList::iterator PEnd = Params->end();
2985 if (MaxParameters)
2986 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002987 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2988 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002989 bool HasDefaultArg = false;
2990 std::string PlaceholderStr;
2991 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2992 if (TTP->wasDeclaredWithTypename())
2993 PlaceholderStr = "typename";
2994 else
2995 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002996
Douglas Gregor3545ff42009-09-21 16:56:56 +00002997 if (TTP->getIdentifier()) {
2998 PlaceholderStr += ' ';
2999 PlaceholderStr += TTP->getIdentifier()->getName();
3000 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003001
Douglas Gregor3545ff42009-09-21 16:56:56 +00003002 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003003 } else if (NonTypeTemplateParmDecl *NTTP =
3004 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003005 if (NTTP->getIdentifier())
3006 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00003007 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003008 HasDefaultArg = NTTP->hasDefaultArgument();
3009 } else {
3010 assert(isa<TemplateTemplateParmDecl>(*P));
3011 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003012
Douglas Gregor3545ff42009-09-21 16:56:56 +00003013 // Since putting the template argument list into the placeholder would
3014 // be very, very long, we just use an abbreviation.
3015 PlaceholderStr = "template<...> class";
3016 if (TTP->getIdentifier()) {
3017 PlaceholderStr += ' ';
3018 PlaceholderStr += TTP->getIdentifier()->getName();
3019 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003020
Douglas Gregor3545ff42009-09-21 16:56:56 +00003021 HasDefaultArg = TTP->hasDefaultArgument();
3022 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003023
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003024 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003025 // When we see an optional default argument, put that argument and
3026 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003027 CodeCompletionBuilder Opt(Result.getAllocator(),
3028 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003029 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003030 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00003031 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003032 P - Params->begin(), true);
3033 Result.AddOptionalChunk(Opt.TakeString());
3034 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003035 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003036
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003037 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003038
Douglas Gregor3545ff42009-09-21 16:56:56 +00003039 if (FirstParameter)
3040 FirstParameter = false;
3041 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003042 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003043
Douglas Gregor3545ff42009-09-21 16:56:56 +00003044 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003045 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003046 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003047 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003048}
3049
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003050/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00003051/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00003052static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
3053 NestedNameSpecifier *Qualifier,
3054 bool QualifierIsInformative,
3055 ASTContext &Context,
3056 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003057 if (!Qualifier)
3058 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003059
Douglas Gregorf2510672009-09-21 19:57:38 +00003060 std::string PrintedNNS;
3061 {
3062 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00003063 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00003064 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00003065 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003066 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00003067 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003068 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00003069}
3070
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003071static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003072AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003073 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00003074 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003075 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00003076 return;
3077
Douglas Gregor304f9b02011-02-01 21:15:40 +00003078 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003079
Douglas Gregor304f9b02011-02-01 21:15:40 +00003080 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003081 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003082 Result.AddInformativeChunk(" const");
3083 return;
3084 }
3085
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003086 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003087 Result.AddInformativeChunk(" volatile");
3088 return;
3089 }
3090
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003091 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003092 Result.AddInformativeChunk(" restrict");
3093 return;
3094 }
3095
3096 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00003097 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00003098 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00003099 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00003100 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00003101 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00003102 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00003103 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003104 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00003105}
3106
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003107/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00003108static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003109 const NamedDecl *ND,
3110 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00003111 DeclarationName Name = ND->getDeclName();
3112 if (!Name)
3113 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003114
Douglas Gregor0212fd72010-09-21 16:06:22 +00003115 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003116 case DeclarationName::CXXOperatorName: {
3117 const char *OperatorName = nullptr;
3118 switch (Name.getCXXOverloadedOperator()) {
3119 case OO_None:
3120 case OO_Conditional:
3121 case NUM_OVERLOADED_OPERATORS:
3122 OperatorName = "operator";
3123 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003124
Fangrui Song050229d2018-11-24 00:14:31 +00003125#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
3126 case OO_##Name: \
3127 OperatorName = "operator" Spelling; \
3128 break;
3129#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00003130#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003131
Fangrui Song050229d2018-11-24 00:14:31 +00003132 case OO_New:
3133 OperatorName = "operator new";
3134 break;
3135 case OO_Delete:
3136 OperatorName = "operator delete";
3137 break;
3138 case OO_Array_New:
3139 OperatorName = "operator new[]";
3140 break;
3141 case OO_Array_Delete:
3142 OperatorName = "operator delete[]";
3143 break;
3144 case OO_Call:
3145 OperatorName = "operator()";
3146 break;
3147 case OO_Subscript:
3148 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003149 break;
3150 }
Fangrui Song050229d2018-11-24 00:14:31 +00003151 Result.AddTypedTextChunk(OperatorName);
3152 break;
3153 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003154
Douglas Gregor0212fd72010-09-21 16:06:22 +00003155 case DeclarationName::Identifier:
3156 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003157 case DeclarationName::CXXDestructorName:
3158 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003159 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003160 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003161 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003162
Richard Smith35845152017-02-07 01:37:30 +00003163 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003164 case DeclarationName::CXXUsingDirective:
3165 case DeclarationName::ObjCZeroArgSelector:
3166 case DeclarationName::ObjCOneArgSelector:
3167 case DeclarationName::ObjCMultiArgSelector:
3168 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003169
Douglas Gregor0212fd72010-09-21 16:06:22 +00003170 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003171 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003172 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003173 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003174 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003175 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003176 Record = InjectedTy->getDecl();
3177 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003178 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003179 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003180 break;
3181 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003182
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003183 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003184 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003185 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003186 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003187 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003188 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003189 }
3190 break;
3191 }
3192 }
3193}
3194
Fangrui Song050229d2018-11-24 00:14:31 +00003195CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3196 Sema &S, const CodeCompletionContext &CCContext,
3197 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3198 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003199 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3200 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003201}
3202
Eric Liu00f43c92018-07-06 09:43:57 +00003203CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3204 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3205 CodeCompletionTUInfo &CCTUInfo) {
3206 assert(Kind == RK_Macro);
3207 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3208 const MacroInfo *MI = PP.getMacroInfo(Macro);
3209 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3210
3211 if (!MI || !MI->isFunctionLike())
3212 return Result.TakeString();
3213
3214 // Format a function-like macro with placeholders for the arguments.
3215 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3216 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3217
3218 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3219 if (MI->isC99Varargs()) {
3220 --AEnd;
3221
3222 if (A == AEnd) {
3223 Result.AddPlaceholderChunk("...");
3224 }
3225 }
3226
3227 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3228 if (A != MI->param_begin())
3229 Result.AddChunk(CodeCompletionString::CK_Comma);
3230
3231 if (MI->isVariadic() && (A + 1) == AEnd) {
3232 SmallString<32> Arg = (*A)->getName();
3233 if (MI->isC99Varargs())
3234 Arg += ", ...";
3235 else
3236 Arg += "...";
3237 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3238 break;
3239 }
3240
3241 // Non-variadic macros are simple.
3242 Result.AddPlaceholderChunk(
3243 Result.getAllocator().CopyString((*A)->getName()));
3244 }
3245 Result.AddChunk(CodeCompletionString::CK_RightParen);
3246 return Result.TakeString();
3247}
3248
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003249/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003250/// result.
3251///
3252/// \returns Either a new, heap-allocated code completion string describing
3253/// how to use this result, or NULL to indicate that the string or name of the
3254/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003255CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3256 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3257 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3258 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003259 if (Kind == RK_Macro)
3260 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3261
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003262 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003263
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003264 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003265 if (Kind == RK_Pattern) {
3266 Pattern->Priority = Priority;
3267 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003268
Douglas Gregor78254c82012-03-27 23:34:16 +00003269 if (Declaration) {
3270 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003271 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003272 if (const RawComment *RC =
3273 getPatternCompletionComment(Ctx, Declaration)) {
3274 Result.addBriefComment(RC->getBriefText(Ctx));
3275 Pattern->BriefComment = Result.getBriefComment();
3276 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003277 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003278
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003279 return Pattern;
3280 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003281
Douglas Gregorf09935f2009-12-01 05:55:20 +00003282 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003283 Result.AddTypedTextChunk(Keyword);
3284 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003285 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003286 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003287 return createCodeCompletionStringForDecl(
3288 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003289}
3290
Ilya Biryukovcabab292019-05-24 10:18:39 +00003291static void printOverrideString(const CodeCompletionString &CCS,
3292 std::string &BeforeName,
3293 std::string &NameAndSignature) {
3294 bool SeenTypedChunk = false;
3295 for (auto &Chunk : CCS) {
3296 if (Chunk.Kind == CodeCompletionString::CK_Optional) {
3297 assert(SeenTypedChunk && "optional parameter before name");
3298 // Note that we put all chunks inside into NameAndSignature.
3299 printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature);
3300 continue;
3301 }
3302 SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText;
3303 if (SeenTypedChunk)
3304 NameAndSignature += Chunk.Text;
3305 else
3306 BeforeName += Chunk.Text;
3307 }
3308}
3309
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003310CodeCompletionString *
3311CodeCompletionResult::createCodeCompletionStringForOverride(
3312 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3313 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3314 PrintingPolicy &Policy) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003315 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3316 /*IncludeBriefComments=*/false,
3317 CCContext, Policy);
Ilya Biryukovcabab292019-05-24 10:18:39 +00003318 std::string BeforeName;
3319 std::string NameAndSignature;
3320 // For overrides all chunks go into the result, none are informative.
3321 printOverrideString(*CCS, BeforeName, NameAndSignature);
3322 NameAndSignature += " override";
3323
3324 Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));
3325 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3326 Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003327 return Result.TakeString();
3328}
3329
3330CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3331 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3332 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3333 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003334 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003335 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003336
3337 if (IncludeBriefComments) {
3338 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003339 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003340 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003341 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003342 }
3343
Douglas Gregor9eb77012009-11-07 00:00:49 +00003344 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003345 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003346 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003347 Result.AddTextChunk("::");
3348 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003349 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003350
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003351 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3352 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003353
Douglas Gregorc3425b12015-07-07 06:20:19 +00003354 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003355
Fangrui Song050229d2018-11-24 00:14:31 +00003356 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003357 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003358 Ctx, Policy);
3359 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003360 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003361 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003362 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003363 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003364 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003365 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003366
Fangrui Song050229d2018-11-24 00:14:31 +00003367 if (const FunctionTemplateDecl *FunTmpl =
3368 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003369 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003370 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003371 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003372 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003373
Douglas Gregor3545ff42009-09-21 16:56:56 +00003374 // Figure out which template parameters are deduced (or have default
3375 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003376 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003377 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003378 unsigned LastDeducibleArgument;
3379 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3380 --LastDeducibleArgument) {
3381 if (!Deduced[LastDeducibleArgument - 1]) {
3382 // C++0x: Figure out if the template argument has a default. If so,
3383 // the user doesn't need to type this argument.
3384 // FIXME: We need to abstract template parameters better!
3385 bool HasDefaultArg = false;
3386 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003387 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003388 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3389 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003390 else if (NonTypeTemplateParmDecl *NTTP =
3391 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003392 HasDefaultArg = NTTP->hasDefaultArgument();
3393 else {
3394 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003395 HasDefaultArg =
3396 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003397 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003398
Douglas Gregor3545ff42009-09-21 16:56:56 +00003399 if (!HasDefaultArg)
3400 break;
3401 }
3402 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003403
Douglas Gregor3545ff42009-09-21 16:56:56 +00003404 if (LastDeducibleArgument) {
3405 // Some of the function template arguments cannot be deduced from a
3406 // function call, so we introduce an explicit template argument list
3407 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003408 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003409 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003410 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003411 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003412 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003413
Douglas Gregor3545ff42009-09-21 16:56:56 +00003414 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003415 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003416 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003417 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003418 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003419 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003420 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003421
Fangrui Song050229d2018-11-24 00:14:31 +00003422 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003423 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003424 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003425 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003426 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003427 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003428 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003429 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003430 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003431 }
Fangrui Song050229d2018-11-24 00:14:31 +00003432 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003433 Selector Sel = Method->getSelector();
3434 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003435 Result.AddTypedTextChunk(
3436 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003437 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003438 }
3439
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003440 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003441 SelName += ':';
3442 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003443 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003444 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003445 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003446
Douglas Gregor1b605f72009-11-19 01:08:35 +00003447 // If there is only one parameter, and we're past it, add an empty
3448 // typed-text chunk since there is nothing to type.
3449 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003450 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003451 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003452 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003453 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003454 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003455 P != PEnd; (void)++P, ++Idx) {
3456 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003457 std::string Keyword;
3458 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003459 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003460 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003461 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003462 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003463 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003464 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003465 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003466 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003467 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003468
Douglas Gregor1b605f72009-11-19 01:08:35 +00003469 // If we're before the starting parameter, skip the placeholder.
3470 if (Idx < StartParameter)
3471 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003472
3473 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003474 QualType ParamType = (*P)->getType();
3475 Optional<ArrayRef<QualType>> ObjCSubsts;
3476 if (!CCContext.getBaseType().isNull())
3477 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3478
3479 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3480 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003481 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003482 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003483 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003484 ParamType = ParamType.substObjCTypeArgs(
3485 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003486 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003487 ParamType);
3488 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003489 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003490 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003491 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003492 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003493
Douglas Gregor400f5972010-08-31 05:13:43 +00003494 if (Method->isVariadic() && (P + 1) == PEnd)
3495 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003496
Douglas Gregor95887f92010-07-08 23:20:03 +00003497 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003498 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003499 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003500 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003501 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003502 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003503 }
3504
Douglas Gregor04c5f972009-12-23 00:21:46 +00003505 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003506 if (Method->param_size() == 0) {
3507 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003508 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003509 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003510 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003511 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003512 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003513 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003514
Richard Smith20e883e2015-04-29 23:20:19 +00003515 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003516 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003517
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003518 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003519 }
3520
Douglas Gregorf09935f2009-12-01 05:55:20 +00003521 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003522 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003523 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003524
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003525 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003526 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003527 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003528}
3529
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003530const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3531 const NamedDecl *ND) {
3532 if (!ND)
3533 return nullptr;
3534 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3535 return RC;
3536
3537 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003538 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003539 if (!M)
3540 return nullptr;
3541 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3542 if (!PDecl)
3543 return nullptr;
3544
3545 return Ctx.getRawCommentForAnyRedecl(PDecl);
3546}
3547
3548const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3549 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003550 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003551 if (!M || !M->isPropertyAccessor())
3552 return nullptr;
3553
3554 // Provide code completion comment for self.GetterName where
3555 // GetterName is the getter method for a property with name
3556 // different from the property name (declared via a property
3557 // getter attribute.
3558 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3559 if (!PDecl)
3560 return nullptr;
3561 if (PDecl->getGetterName() == M->getSelector() &&
3562 PDecl->getIdentifier() != M->getIdentifier()) {
3563 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3564 return RC;
3565 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3566 return RC;
3567 }
3568 return nullptr;
3569}
3570
3571const RawComment *clang::getParameterComment(
3572 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003573 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003574 auto FDecl = Result.getFunction();
3575 if (!FDecl)
3576 return nullptr;
3577 if (ArgIndex < FDecl->getNumParams())
3578 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3579 return nullptr;
3580}
3581
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003582/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003583/// string.
3584static void AddOverloadParameterChunks(ASTContext &Context,
3585 const PrintingPolicy &Policy,
3586 const FunctionDecl *Function,
3587 const FunctionProtoType *Prototype,
3588 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003589 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003590 bool InOptional = false) {
3591 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003592 unsigned NumParams =
3593 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003594
3595 for (unsigned P = Start; P != NumParams; ++P) {
3596 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3597 // When we see an optional default argument, put that argument and
3598 // the remaining default arguments into a new, optional string.
3599 CodeCompletionBuilder Opt(Result.getAllocator(),
3600 Result.getCodeCompletionTUInfo());
3601 if (!FirstParameter)
3602 Opt.AddChunk(CodeCompletionString::CK_Comma);
3603 // Optional sections are nested.
3604 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3605 CurrentArg, P, /*InOptional=*/true);
3606 Result.AddOptionalChunk(Opt.TakeString());
3607 return;
3608 }
3609
3610 if (FirstParameter)
3611 FirstParameter = false;
3612 else
3613 Result.AddChunk(CodeCompletionString::CK_Comma);
3614
3615 InOptional = false;
3616
3617 // Format the placeholder string.
3618 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003619 if (Function) {
3620 const ParmVarDecl *Param = Function->getParamDecl(P);
3621 Placeholder = FormatFunctionParameter(Policy, Param);
3622 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003623 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3624 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003625 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003626 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003627 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003628
3629 if (P == CurrentArg)
3630 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003631 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003632 else
3633 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3634 }
3635
3636 if (Prototype && Prototype->isVariadic()) {
3637 CodeCompletionBuilder Opt(Result.getAllocator(),
3638 Result.getCodeCompletionTUInfo());
3639 if (!FirstParameter)
3640 Opt.AddChunk(CodeCompletionString::CK_Comma);
3641
3642 if (CurrentArg < NumParams)
3643 Opt.AddPlaceholderChunk("...");
3644 else
3645 Opt.AddCurrentParameterChunk("...");
3646
3647 Result.AddOptionalChunk(Opt.TakeString());
3648 }
3649}
3650
Douglas Gregorf0f51982009-09-23 00:34:09 +00003651CodeCompletionString *
3652CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003653 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3654 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003655 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Sam McCallfa3b87f2019-11-15 14:52:04 +01003656 // Show signatures of constructors as they are declared:
3657 // vector(int n) rather than vector<string>(int n)
3658 // This is less noisy without being less clear, and avoids tricky cases.
3659 Policy.SuppressTemplateArgsInCXXConstructors = true;
John McCall31168b02011-06-15 23:02:42 +00003660
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003661 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003662 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3663 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003664 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003665 const FunctionProtoType *Proto =
3666 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003667 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003668 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003669 // highlighted ellipsis.
3670 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003671 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003672 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003673 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3674 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3675 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003676 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003677 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003678
3679 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003680 if (IncludeBriefComments) {
3681 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003682 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003683 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003684 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003685 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003686 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003687 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003688 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003689 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003690 }
Alp Toker314cc812014-01-25 16:55:45 +00003691
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003692 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003693 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3694 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003695 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003696
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003697 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003698}
3699
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003700unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003701 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003702 bool PreferredTypeIsPointer) {
3703 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003704
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003705 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003706 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003707 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003708 Priority = CCP_Constant;
3709 if (PreferredTypeIsPointer)
3710 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003711 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003712 // Treat "YES", "NO", "true", and "false" as constants.
3713 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3714 MacroName.equals("true") || MacroName.equals("false"))
3715 Priority = CCP_Constant;
3716 // Treat "bool" as a type.
3717 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003718 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003719
Douglas Gregor6e240332010-08-16 16:18:59 +00003720 return Priority;
3721}
3722
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003723CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003724 if (!D)
3725 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003726
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003727 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003728 case Decl::Enum:
3729 return CXCursor_EnumDecl;
3730 case Decl::EnumConstant:
3731 return CXCursor_EnumConstantDecl;
3732 case Decl::Field:
3733 return CXCursor_FieldDecl;
3734 case Decl::Function:
3735 return CXCursor_FunctionDecl;
3736 case Decl::ObjCCategory:
3737 return CXCursor_ObjCCategoryDecl;
3738 case Decl::ObjCCategoryImpl:
3739 return CXCursor_ObjCCategoryImplDecl;
3740 case Decl::ObjCImplementation:
3741 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003742
Fangrui Song050229d2018-11-24 00:14:31 +00003743 case Decl::ObjCInterface:
3744 return CXCursor_ObjCInterfaceDecl;
3745 case Decl::ObjCIvar:
3746 return CXCursor_ObjCIvarDecl;
3747 case Decl::ObjCMethod:
3748 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3749 ? CXCursor_ObjCInstanceMethodDecl
3750 : CXCursor_ObjCClassMethodDecl;
3751 case Decl::CXXMethod:
3752 return CXCursor_CXXMethod;
3753 case Decl::CXXConstructor:
3754 return CXCursor_Constructor;
3755 case Decl::CXXDestructor:
3756 return CXCursor_Destructor;
3757 case Decl::CXXConversion:
3758 return CXCursor_ConversionFunction;
3759 case Decl::ObjCProperty:
3760 return CXCursor_ObjCPropertyDecl;
3761 case Decl::ObjCProtocol:
3762 return CXCursor_ObjCProtocolDecl;
3763 case Decl::ParmVar:
3764 return CXCursor_ParmDecl;
3765 case Decl::Typedef:
3766 return CXCursor_TypedefDecl;
3767 case Decl::TypeAlias:
3768 return CXCursor_TypeAliasDecl;
3769 case Decl::TypeAliasTemplate:
3770 return CXCursor_TypeAliasTemplateDecl;
3771 case Decl::Var:
3772 return CXCursor_VarDecl;
3773 case Decl::Namespace:
3774 return CXCursor_Namespace;
3775 case Decl::NamespaceAlias:
3776 return CXCursor_NamespaceAlias;
3777 case Decl::TemplateTypeParm:
3778 return CXCursor_TemplateTypeParameter;
3779 case Decl::NonTypeTemplateParm:
3780 return CXCursor_NonTypeTemplateParameter;
3781 case Decl::TemplateTemplateParm:
3782 return CXCursor_TemplateTemplateParameter;
3783 case Decl::FunctionTemplate:
3784 return CXCursor_FunctionTemplate;
3785 case Decl::ClassTemplate:
3786 return CXCursor_ClassTemplate;
3787 case Decl::AccessSpec:
3788 return CXCursor_CXXAccessSpecifier;
3789 case Decl::ClassTemplatePartialSpecialization:
3790 return CXCursor_ClassTemplatePartialSpecialization;
3791 case Decl::UsingDirective:
3792 return CXCursor_UsingDirective;
3793 case Decl::StaticAssert:
3794 return CXCursor_StaticAssert;
3795 case Decl::Friend:
3796 return CXCursor_FriendDecl;
3797 case Decl::TranslationUnit:
3798 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003799
Fangrui Song050229d2018-11-24 00:14:31 +00003800 case Decl::Using:
3801 case Decl::UnresolvedUsingValue:
3802 case Decl::UnresolvedUsingTypename:
3803 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003804
Fangrui Song050229d2018-11-24 00:14:31 +00003805 case Decl::ObjCPropertyImpl:
3806 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3807 case ObjCPropertyImplDecl::Dynamic:
3808 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003809
Fangrui Song050229d2018-11-24 00:14:31 +00003810 case ObjCPropertyImplDecl::Synthesize:
3811 return CXCursor_ObjCSynthesizeDecl;
3812 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003813 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003814
3815 case Decl::Import:
3816 return CXCursor_ModuleImportDecl;
3817
3818 case Decl::ObjCTypeParam:
3819 return CXCursor_TemplateTypeParameter;
3820
3821 default:
3822 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3823 switch (TD->getTagKind()) {
3824 case TTK_Interface: // fall through
3825 case TTK_Struct:
3826 return CXCursor_StructDecl;
3827 case TTK_Class:
3828 return CXCursor_ClassDecl;
3829 case TTK_Union:
3830 return CXCursor_UnionDecl;
3831 case TTK_Enum:
3832 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003833 }
Fangrui Song050229d2018-11-24 00:14:31 +00003834 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003835 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003836
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003837 return CXCursor_UnexposedDecl;
3838}
3839
Douglas Gregor55b037b2010-07-08 20:55:51 +00003840static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003841 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003842 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003843 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003844
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003845 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003846
Eric Liu88de9f62018-09-19 09:34:55 +00003847 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3848 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003849 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003850 auto MD = PP.getMacroDefinition(M->first);
3851 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003852 MacroInfo *MI = MD.getMacroInfo();
3853 if (MI && MI->isUsedForHeaderGuard())
3854 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003855
Eric Liud485df12018-09-05 14:59:17 +00003856 Results.AddResult(
3857 Result(M->first, MI,
3858 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3859 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003860 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003861 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003862
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003863 Results.ExitScope();
3864}
3865
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003866static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003867 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003868 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003869
Douglas Gregorce0e8562010-08-23 21:54:33 +00003870 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003871
Douglas Gregorce0e8562010-08-23 21:54:33 +00003872 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3873 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003874 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003875 Results.AddResult(Result("__func__", CCP_Constant));
3876 Results.ExitScope();
3877}
3878
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003879static void HandleCodeCompleteResults(Sema *S,
3880 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003881 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003882 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003883 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003884 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003885 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003886}
3887
Ilya Biryukov41109672018-12-13 15:36:32 +00003888static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003889mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003890 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003891 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003892 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003893
John McCallfaf5fb42010-08-26 23:41:50 +00003894 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003895 return CodeCompletionContext::CCC_ClassStructUnion;
3896
John McCallfaf5fb42010-08-26 23:41:50 +00003897 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003898 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003899
John McCallfaf5fb42010-08-26 23:41:50 +00003900 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003901 return CodeCompletionContext::CCC_ObjCImplementation;
3902
John McCallfaf5fb42010-08-26 23:41:50 +00003903 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003904 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003905
John McCallfaf5fb42010-08-26 23:41:50 +00003906 case Sema::PCC_Template:
3907 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003908 if (S.CurContext->isFileContext())
3909 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003910 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003911 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003912 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003913
John McCallfaf5fb42010-08-26 23:41:50 +00003914 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003915 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003916
John McCallfaf5fb42010-08-26 23:41:50 +00003917 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003918 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003919 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003920 return CodeCompletionContext::CCC_ParenthesizedExpression;
3921 else
3922 return CodeCompletionContext::CCC_Expression;
3923
3924 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003925 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003926 case Sema::PCC_Condition:
3927 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3928 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003929
John McCallfaf5fb42010-08-26 23:41:50 +00003930 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003931 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003932
John McCallfaf5fb42010-08-26 23:41:50 +00003933 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003934 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003935
3936 case Sema::PCC_ParenthesizedExpression:
3937 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003938
Douglas Gregor80039242011-02-15 20:33:25 +00003939 case Sema::PCC_LocalDeclarationSpecifiers:
3940 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003941 }
David Blaikie8a40f702012-01-17 06:56:22 +00003942
3943 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003944}
3945
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003946/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003947/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003948/// overridden function as well as adding new functionality.
3949///
3950/// \param S The semantic analysis object for which we are generating results.
3951///
3952/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003953/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003954static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3955 ResultBuilder &Results) {
3956 // Look through blocks.
3957 DeclContext *CurContext = S.CurContext;
3958 while (isa<BlockDecl>(CurContext))
3959 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003960
Douglas Gregorac322ec2010-08-27 21:18:54 +00003961 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3962 if (!Method || !Method->isVirtual())
3963 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003964
3965 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003966 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003967 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003968 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003969 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003970
Douglas Gregor75acd922011-09-27 23:30:47 +00003971 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003972 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003973 CodeCompletionBuilder Builder(Results.getAllocator(),
3974 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003975 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3976 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003977
Douglas Gregorac322ec2010-08-27 21:18:54 +00003978 // If we need a nested-name-specifier, add one now.
3979 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003980 NestedNameSpecifier *NNS = getRequiredQualification(
3981 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003982 if (NNS) {
3983 std::string Str;
3984 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003985 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003986 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003987 }
3988 } else if (!InContext->Equals(Overridden->getDeclContext()))
3989 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003990
Fangrui Song050229d2018-11-24 00:14:31 +00003991 Builder.AddTypedTextChunk(
3992 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003993 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003994 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003995 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003996 if (FirstParam)
3997 FirstParam = false;
3998 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003999 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004000
Aaron Ballman43b68be2014-03-07 17:50:17 +00004001 Builder.AddPlaceholderChunk(
4002 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004003 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004004 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00004005 Results.AddResult(CodeCompletionResult(
4006 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
4007 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004008 Results.Ignore(Overridden);
4009 }
4010}
4011
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004012void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00004013 ModuleIdPath Path) {
4014 typedef CodeCompletionResult Result;
4015 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004016 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00004017 CodeCompletionContext::CCC_Other);
4018 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004019
Douglas Gregor07f43572012-01-29 18:15:03 +00004020 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004021 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00004022 typedef CodeCompletionResult Result;
4023 if (Path.empty()) {
4024 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00004025 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00004026 PP.getHeaderSearchInfo().collectAllModules(Modules);
4027 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
4028 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004029 Builder.getAllocator().CopyString(Modules[I]->Name));
4030 Results.AddResult(Result(
4031 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4032 Modules[I]->isAvailable() ? CXAvailability_Available
4033 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004034 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00004035 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00004036 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00004037 Module *Mod =
4038 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
4039 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00004040 // Enumerate submodules.
4041 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004042 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00004043 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00004044 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004045
Douglas Gregor07f43572012-01-29 18:15:03 +00004046 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004047 Builder.getAllocator().CopyString((*Sub)->Name));
4048 Results.AddResult(Result(
4049 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4050 (*Sub)->isAvailable() ? CXAvailability_Available
4051 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004052 }
4053 }
4054 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004055 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00004056 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004057 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00004058}
4059
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004060void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004061 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004062 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004063 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004064 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004065 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004066
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004067 // Determine how to filter results, e.g., so that the names of
4068 // values (functions, enumerators, function templates, etc.) are
4069 // only allowed where we can have an expression.
4070 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004071 case PCC_Namespace:
4072 case PCC_Class:
4073 case PCC_ObjCInterface:
4074 case PCC_ObjCImplementation:
4075 case PCC_ObjCInstanceVariableList:
4076 case PCC_Template:
4077 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004078 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004079 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004080 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4081 break;
4082
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004083 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00004084 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00004085 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004086 case PCC_ForInit:
4087 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00004088 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00004089 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4090 else
4091 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004092
David Blaikiebbafb8a2012-03-11 07:00:24 +00004093 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00004094 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004095 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004096
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004097 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00004098 // Unfiltered
4099 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004100 }
4101
Douglas Gregor9be0ed42010-08-26 16:36:48 +00004102 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004103 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00004104 auto ThisType = getCurrentThisType();
4105 if (!ThisType.isNull())
Sam McCall3dea5272019-06-10 15:17:52 +00004106 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(),
4107 VK_LValue);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004108
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004109 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004110 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004111 CodeCompleter->includeGlobals(),
4112 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00004113
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004114 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00004115 Results.ExitScope();
4116
Douglas Gregorce0e8562010-08-23 21:54:33 +00004117 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00004118 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004119 case PCC_Expression:
4120 case PCC_Statement:
4121 case PCC_RecoveryInFunction:
4122 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004123 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004124 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004125
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004126 case PCC_Namespace:
4127 case PCC_Class:
4128 case PCC_ObjCInterface:
4129 case PCC_ObjCImplementation:
4130 case PCC_ObjCInstanceVariableList:
4131 case PCC_Template:
4132 case PCC_MemberTemplate:
4133 case PCC_ForInit:
4134 case PCC_Condition:
4135 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004136 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004137 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00004138 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004139
Douglas Gregor9eb77012009-11-07 00:00:49 +00004140 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004141 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004142
Douglas Gregor50832e02010-09-20 22:39:41 +00004143 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004144 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00004145}
4146
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004147static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004148 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004149 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00004150 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004151 ResultBuilder &Results);
4152
4153void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
4154 bool AllowNonIdentifiers,
4155 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00004156 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004157 ResultBuilder Results(
4158 *this, CodeCompleter->getAllocator(),
4159 CodeCompleter->getCodeCompletionTUInfo(),
4160 AllowNestedNameSpecifiers
4161 // FIXME: Try to separate codepath leading here to deduce whether we
4162 // need an existing symbol or a new one.
4163 ? CodeCompletionContext::CCC_SymbolOrNewName
4164 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004165 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004166
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004167 // Type qualifiers can come after names.
4168 Results.AddResult(Result("const"));
4169 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004170 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004171 Results.AddResult(Result("restrict"));
4172
David Blaikiebbafb8a2012-03-11 07:00:24 +00004173 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004174 if (getLangOpts().CPlusPlus11 &&
4175 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4176 DS.getTypeSpecType() == DeclSpec::TST_struct))
4177 Results.AddResult("final");
4178
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004179 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004180 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004181 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004182
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004183 // Add nested-name-specifiers.
4184 if (AllowNestedNameSpecifiers) {
4185 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004186 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004187 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4188 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004189 CodeCompleter->includeGlobals(),
4190 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004191 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004192 }
4193 }
4194 Results.ExitScope();
4195
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004196 // If we're in a context where we might have an expression (rather than a
4197 // declaration), and what we've seen so far is an Objective-C type that could
4198 // be a receiver of a class message, this may be a class message send with
4199 // the initial opening bracket '[' missing. Add appropriate completions.
4200 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004201 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004202 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004203 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4204 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004205 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004206 (S->getFlags() & Scope::DeclScope) != 0 &&
4207 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004208 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4209 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004210 ParsedType T = DS.getRepAsType();
4211 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004212 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004213 }
4214
Douglas Gregor56ccce02010-08-24 04:59:56 +00004215 // Note that we intentionally suppress macro results here, since we do not
4216 // encourage using macros to produce the names of entities.
4217
Fangrui Song050229d2018-11-24 00:14:31 +00004218 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004219 Results.data(), Results.size());
4220}
4221
Douglas Gregor68762e72010-08-23 21:17:50 +00004222struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004223 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4224 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004225 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004226 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004227
Douglas Gregor68762e72010-08-23 21:17:50 +00004228 QualType PreferredType;
4229 bool IntegralConstantExpression;
4230 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004231 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004232 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004233};
4234
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004235namespace {
4236/// Information that allows to avoid completing redundant enumerators.
4237struct CoveredEnumerators {
4238 llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
4239 NestedNameSpecifier *SuggestedQualifier = nullptr;
4240};
4241} // namespace
4242
4243static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
4244 EnumDecl *Enum, DeclContext *CurContext,
4245 const CoveredEnumerators &Enumerators) {
4246 NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
4247 if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
4248 // If there are no prior enumerators in C++, check whether we have to
4249 // qualify the names of the enumerators that we suggest, because they
4250 // may not be visible in this scope.
4251 Qualifier = getRequiredQualification(Context, CurContext, Enum);
4252 }
4253
4254 Results.EnterNewScope();
4255 for (auto *E : Enum->enumerators()) {
4256 if (Enumerators.Seen.count(E))
4257 continue;
4258
4259 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
4260 Results.AddResult(R, CurContext, nullptr, false);
4261 }
4262 Results.ExitScope();
4263}
4264
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004265/// Try to find a corresponding FunctionProtoType for function-like types (e.g.
4266/// function pointers, std::function, etc).
4267static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) {
4268 assert(!T.isNull());
4269 // Try to extract first template argument from std::function<> and similar.
4270 // Note we only handle the sugared types, they closely match what users wrote.
4271 // We explicitly choose to not handle ClassTemplateSpecializationDecl.
4272 if (auto *Specialization = T->getAs<TemplateSpecializationType>()) {
4273 if (Specialization->getNumArgs() != 1)
4274 return nullptr;
4275 const TemplateArgument &Argument = Specialization->getArg(0);
4276 if (Argument.getKind() != TemplateArgument::Type)
4277 return nullptr;
4278 return Argument.getAsType()->getAs<FunctionProtoType>();
4279 }
4280 // Handle other cases.
4281 if (T->isPointerType())
4282 T = T->getPointeeType();
4283 return T->getAs<FunctionProtoType>();
4284}
4285
4286/// Adds a pattern completion for a lambda expression with the specified
4287/// parameter types and placeholders for parameter names.
4288static void AddLambdaCompletion(ResultBuilder &Results,
4289 llvm::ArrayRef<QualType> Parameters,
4290 const LangOptions &LangOpts) {
Ilya Biryukovfd11a5f2019-05-23 16:39:26 +00004291 if (!Results.includeCodePatterns())
4292 return;
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004293 CodeCompletionBuilder Completion(Results.getAllocator(),
4294 Results.getCodeCompletionTUInfo());
4295 // [](<parameters>) {}
4296 Completion.AddChunk(CodeCompletionString::CK_LeftBracket);
4297 Completion.AddPlaceholderChunk("=");
4298 Completion.AddChunk(CodeCompletionString::CK_RightBracket);
4299 if (!Parameters.empty()) {
4300 Completion.AddChunk(CodeCompletionString::CK_LeftParen);
4301 bool First = true;
4302 for (auto Parameter : Parameters) {
4303 if (!First)
4304 Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma);
4305 else
4306 First = false;
4307
4308 constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!";
4309 std::string Type = NamePlaceholder;
4310 Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts));
4311 llvm::StringRef Prefix, Suffix;
4312 std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder);
4313 Prefix = Prefix.rtrim();
4314 Suffix = Suffix.ltrim();
4315
4316 Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix));
4317 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4318 Completion.AddPlaceholderChunk("parameter");
4319 Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix));
4320 };
4321 Completion.AddChunk(CodeCompletionString::CK_RightParen);
4322 }
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004323 Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004324 Completion.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004325 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004326 Completion.AddPlaceholderChunk("body");
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004327 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004328 Completion.AddChunk(CodeCompletionString::CK_RightBrace);
4329
4330 Results.AddResult(Completion.TakeString());
4331}
4332
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004333/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004334/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004335void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004336 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004337 ResultBuilder Results(
4338 *this, CodeCompleter->getAllocator(),
4339 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004340 CodeCompletionContext(
4341 Data.IsParenthesized
4342 ? CodeCompletionContext::CCC_ParenthesizedExpression
4343 : CodeCompletionContext::CCC_Expression,
4344 Data.PreferredType));
4345 auto PCC =
4346 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004347 if (Data.ObjCCollection)
4348 Results.setFilter(&ResultBuilder::IsObjCCollection);
4349 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004350 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004351 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004352 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4353 else
4354 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004355
4356 if (!Data.PreferredType.isNull())
4357 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004358
Douglas Gregor68762e72010-08-23 21:17:50 +00004359 // Ignore any declarations that we were told that we don't care about.
4360 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4361 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004362
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004363 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004364 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004365 CodeCompleter->includeGlobals(),
4366 CodeCompleter->loadExternal());
4367
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004368 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004369 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004370 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004371
Douglas Gregor55b037b2010-07-08 20:55:51 +00004372 bool PreferredTypeIsPointer = false;
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004373 if (!Data.PreferredType.isNull()) {
Fangrui Song050229d2018-11-24 00:14:31 +00004374 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4375 Data.PreferredType->isMemberPointerType() ||
4376 Data.PreferredType->isBlockPointerType();
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004377 if (Data.PreferredType->isEnumeralType()) {
4378 EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();
4379 if (auto *Def = Enum->getDefinition())
4380 Enum = Def;
4381 // FIXME: collect covered enumerators in cases like:
4382 // if (x == my_enum::one) { ... } else if (x == ^) {}
4383 AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators());
4384 }
4385 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004386
Fangrui Song050229d2018-11-24 00:14:31 +00004387 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004388 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004389 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004390
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004391 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004392 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4393 PreferredTypeIsPointer);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004394
4395 // Complete a lambda expression when preferred type is a function.
4396 if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) {
4397 if (const FunctionProtoType *F =
4398 TryDeconstructFunctionLike(Data.PreferredType))
4399 AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts());
4400 }
4401
Eric Liuf5ba09f2018-07-04 10:01:18 +00004402 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4403 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004404}
4405
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004406void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4407 bool IsParenthesized) {
4408 return CodeCompleteExpression(
4409 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004410}
4411
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004412void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4413 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004414 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004415 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004416 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004417 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004418}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004419
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004420/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004421/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004422typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004423
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004424/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004425static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4426 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4427 if (Interface->hasDefinition())
4428 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004429
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004430 return Interface;
4431 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004432
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004433 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4434 if (Protocol->hasDefinition())
4435 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004436
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004437 return Protocol;
4438 }
4439 return Container;
4440}
4441
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004442/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004443/// declaration \p BD.
4444static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4445 CodeCompletionBuilder &Builder,
4446 const NamedDecl *BD,
4447 const FunctionTypeLoc &BlockLoc,
4448 const FunctionProtoTypeLoc &BlockProtoLoc) {
4449 Builder.AddResultTypeChunk(
4450 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4451 Policy, Builder.getAllocator()));
4452
4453 AddTypedNameChunk(Context, Policy, BD, Builder);
4454 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4455
4456 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4457 Builder.AddPlaceholderChunk("...");
4458 } else {
4459 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4460 if (I)
4461 Builder.AddChunk(CodeCompletionString::CK_Comma);
4462
4463 // Format the placeholder string.
4464 std::string PlaceholderStr =
4465 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4466
4467 if (I == N - 1 && BlockProtoLoc &&
4468 BlockProtoLoc.getTypePtr()->isVariadic())
4469 PlaceholderStr += ", ...";
4470
4471 // Add the placeholder string.
4472 Builder.AddPlaceholderChunk(
4473 Builder.getAllocator().CopyString(PlaceholderStr));
4474 }
4475 }
4476
4477 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4478}
4479
Fangrui Song050229d2018-11-24 00:14:31 +00004480static void
4481AddObjCProperties(const CodeCompletionContext &CCContext,
4482 ObjCContainerDecl *Container, bool AllowCategories,
4483 bool AllowNullaryMethods, DeclContext *CurContext,
4484 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4485 bool IsBaseExprStatement = false,
4486 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004487 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004488
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004489 // Retrieve the definition.
4490 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004491
Douglas Gregor9291bad2009-11-18 01:29:26 +00004492 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004493 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004494 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004495 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004496
Alex Lorenzbaef8022016-11-09 13:43:18 +00004497 // FIXME: Provide block invocation completion for non-statement
4498 // expressions.
4499 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4500 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004501 Result R = Result(P, Results.getBasePriority(P), nullptr);
4502 if (!InOriginalClass)
4503 setInBaseClass(R);
4504 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004505 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004506 }
4507
4508 // Block setter and invocation completion is provided only when we are able
4509 // to find the FunctionProtoTypeLoc with parameter names for the block.
4510 FunctionTypeLoc BlockLoc;
4511 FunctionProtoTypeLoc BlockProtoLoc;
4512 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4513 BlockProtoLoc);
4514 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004515 Result R = Result(P, Results.getBasePriority(P), nullptr);
4516 if (!InOriginalClass)
4517 setInBaseClass(R);
4518 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004519 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004520 }
4521
4522 // The default completion result for block properties should be the block
4523 // invocation completion when the base expression is a statement.
4524 CodeCompletionBuilder Builder(Results.getAllocator(),
4525 Results.getCodeCompletionTUInfo());
4526 AddObjCBlockCall(Container->getASTContext(),
4527 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4528 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004529 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4530 if (!InOriginalClass)
4531 setInBaseClass(R);
4532 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004533
4534 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004535 // statement and the block property is mutable.
4536 if (!P->isReadOnly()) {
4537 CodeCompletionBuilder Builder(Results.getAllocator(),
4538 Results.getCodeCompletionTUInfo());
4539 AddResultTypeChunk(Container->getASTContext(),
4540 getCompletionPrintingPolicy(Results.getSema()), P,
4541 CCContext.getBaseType(), Builder);
4542 Builder.AddTypedTextChunk(
4543 Results.getAllocator().CopyString(P->getName()));
4544 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004545
Alex Lorenzbaef8022016-11-09 13:43:18 +00004546 std::string PlaceholderStr = formatBlockPlaceholder(
4547 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4548 BlockProtoLoc, /*SuppressBlockName=*/true);
4549 // Add the placeholder string.
4550 Builder.AddPlaceholderChunk(
4551 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004552
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004553 // When completing blocks properties that return void the default
4554 // property completion result should show up before the setter,
4555 // otherwise the setter completion should show up before the default
4556 // property completion, as we normally want to use the result of the
4557 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004558 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004559 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004560 Results.getBasePriority(P) +
4561 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4562 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004563 : -CCD_BlockPropertySetter));
4564 if (!InOriginalClass)
4565 setInBaseClass(R);
4566 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004567 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004568 };
4569
4570 if (IsClassProperty) {
4571 for (const auto *P : Container->class_properties())
4572 AddProperty(P);
4573 } else {
4574 for (const auto *P : Container->instance_properties())
4575 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004576 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004577
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004578 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004579 if (AllowNullaryMethods) {
4580 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004581 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004582 // Adds a method result
4583 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4584 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4585 if (!Name)
4586 return;
4587 if (!AddedProperties.insert(Name).second)
4588 return;
4589 CodeCompletionBuilder Builder(Results.getAllocator(),
4590 Results.getCodeCompletionTUInfo());
4591 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4592 Builder.AddTypedTextChunk(
4593 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004594 Result R = Result(Builder.TakeString(), M,
4595 CCP_MemberDeclaration + CCD_MethodAsProperty);
4596 if (!InOriginalClass)
4597 setInBaseClass(R);
4598 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004599 };
4600
4601 if (IsClassProperty) {
4602 for (const auto *M : Container->methods()) {
4603 // Gather the class method that can be used as implicit property
4604 // getters. Methods with arguments or methods that return void aren't
4605 // added to the results as they can't be used as a getter.
4606 if (!M->getSelector().isUnarySelector() ||
4607 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4608 continue;
4609 AddMethod(M);
4610 }
4611 } else {
4612 for (auto *M : Container->methods()) {
4613 if (M->getSelector().isUnarySelector())
4614 AddMethod(M);
4615 }
Douglas Gregor95147142011-05-05 15:50:42 +00004616 }
4617 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004618
Douglas Gregor9291bad2009-11-18 01:29:26 +00004619 // Add properties in referenced protocols.
4620 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004621 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004622 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004623 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004624 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004625 /*InOriginalClass*/ false);
4626 } else if (ObjCInterfaceDecl *IFace =
4627 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004628 if (AllowCategories) {
4629 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004630 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004631 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004632 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004633 IsBaseExprStatement, IsClassProperty,
4634 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004635 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004636
Douglas Gregor9291bad2009-11-18 01:29:26 +00004637 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004638 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004639 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004640 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004641 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004642 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004643
Douglas Gregor9291bad2009-11-18 01:29:26 +00004644 // Look in the superclass.
4645 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004646 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004647 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004648 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004649 /*InOriginalClass*/ false);
4650 } else if (const auto *Category =
4651 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004652 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004653 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004654 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004655 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004656 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004657 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004658 }
4659}
4660
Sam McCall3dea5272019-06-10 15:17:52 +00004661static void AddRecordMembersCompletionResults(
4662 Sema &SemaRef, ResultBuilder &Results, Scope *S, QualType BaseType,
4663 ExprValueKind BaseKind, RecordDecl *RD, Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004664 // Indicate that we are performing a member access, and the cv-qualifiers
4665 // for the base object type.
Sam McCall3dea5272019-06-10 15:17:52 +00004666 Results.setObjectTypeQualifiers(BaseType.getQualifiers(), BaseKind);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004667
4668 // Access to a C/C++ class, struct, or union.
4669 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004670 std::vector<FixItHint> FixIts;
4671 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004672 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004673 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004674 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004675 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004676 /*IncludeDependentBases=*/true,
4677 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004678
4679 if (SemaRef.getLangOpts().CPlusPlus) {
4680 if (!Results.empty()) {
4681 // The "template" keyword can follow "->" or "." in the grammar.
4682 // However, we only want to suggest the template keyword if something
4683 // is dependent.
4684 bool IsDependent = BaseType->isDependentType();
4685 if (!IsDependent) {
4686 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4687 if (DeclContext *Ctx = DepScope->getEntity()) {
4688 IsDependent = Ctx->isDependentContext();
4689 break;
4690 }
4691 }
4692
4693 if (IsDependent)
4694 Results.AddResult(CodeCompletionResult("template"));
4695 }
4696 }
4697}
4698
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004699void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004700 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004701 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004702 bool IsBaseExprStatement,
4703 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004704 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004705 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004706
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004707 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4708 if (ConvertedBase.isInvalid())
4709 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004710 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4711
4712 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004713
4714 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004715 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004716 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004717 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004718
Douglas Gregor21325842011-07-07 16:03:39 +00004719 if (IsArrow) {
4720 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004721 } else {
4722 if (ConvertedBaseType->isObjCObjectPointerType() ||
4723 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004724 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004725 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004726 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4727 }
4728 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004729
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004730 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004731 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004732 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004733 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004734 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004735
Fangrui Song050229d2018-11-24 00:14:31 +00004736 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4737 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004738 if (!Base)
4739 return false;
4740
4741 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4742 if (ConvertedBase.isInvalid())
4743 return false;
4744 Base = ConvertedBase.get();
4745
4746 QualType BaseType = Base->getType();
Sam McCall3dea5272019-06-10 15:17:52 +00004747 ExprValueKind BaseKind = Base->getValueKind();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004748
4749 if (IsArrow) {
Sam McCall3dea5272019-06-10 15:17:52 +00004750 if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004751 BaseType = Ptr->getPointeeType();
Sam McCall3dea5272019-06-10 15:17:52 +00004752 BaseKind = VK_LValue;
4753 } else if (BaseType->isObjCObjectPointerType())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004754 /*Do nothing*/;
4755 else
4756 return false;
4757 }
4758
4759 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Sam McCall3dea5272019-06-10 15:17:52 +00004760 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004761 Record->getDecl(),
4762 std::move(AccessOpFixIt));
4763 } else if (const auto *TST =
4764 BaseType->getAs<TemplateSpecializationType>()) {
4765 TemplateName TN = TST->getTemplateName();
4766 if (const auto *TD =
4767 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4768 CXXRecordDecl *RD = TD->getTemplatedDecl();
Sam McCall3dea5272019-06-10 15:17:52 +00004769 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
4770 RD, std::move(AccessOpFixIt));
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004771 }
4772 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4773 if (auto *RD = ICNT->getDecl())
Sam McCall3dea5272019-06-10 15:17:52 +00004774 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
4775 RD, std::move(AccessOpFixIt));
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004776 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4777 // Objective-C property reference.
4778 AddedPropertiesSet AddedProperties;
4779
4780 if (const ObjCObjectPointerType *ObjCPtr =
4781 BaseType->getAsObjCInterfacePointerType()) {
4782 // Add property results based on our interface.
4783 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4784 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4785 /*AllowNullaryMethods=*/true, CurContext,
4786 AddedProperties, Results, IsBaseExprStatement);
4787 }
4788
4789 // Add properties from the protocols in a qualified interface.
4790 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4791 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4792 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004793 IsBaseExprStatement, /*IsClassProperty*/ false,
4794 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004795 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4796 (!IsArrow && BaseType->isObjCObjectType())) {
4797 // Objective-C instance variable access.
4798 ObjCInterfaceDecl *Class = nullptr;
4799 if (const ObjCObjectPointerType *ObjCPtr =
4800 BaseType->getAs<ObjCObjectPointerType>())
4801 Class = ObjCPtr->getInterfaceDecl();
4802 else
4803 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4804
4805 // Add all ivars from this class and its superclasses.
4806 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004807 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004808 Results.setFilter(&ResultBuilder::IsObjCIvar);
4809 LookupVisibleDecls(
4810 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4811 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4812 }
4813 }
4814
4815 // FIXME: How do we cope with isa?
4816 return true;
4817 };
4818
Douglas Gregor9291bad2009-11-18 01:29:26 +00004819 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004820
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004821 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4822 if (CodeCompleter->includeFixIts()) {
4823 const CharSourceRange OpRange =
4824 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4825 CompletionSucceded |= DoCompletion(
4826 OtherOpBase, !IsArrow,
4827 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004828 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004829
Douglas Gregor9291bad2009-11-18 01:29:26 +00004830 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004831
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004832 if (!CompletionSucceded)
4833 return;
4834
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004835 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004836 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4837 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004838}
4839
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004840void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4841 IdentifierInfo &ClassName,
4842 SourceLocation ClassNameLoc,
4843 bool IsBaseExprStatement) {
4844 IdentifierInfo *ClassNamePtr = &ClassName;
4845 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4846 if (!IFace)
4847 return;
4848 CodeCompletionContext CCContext(
4849 CodeCompletionContext::CCC_ObjCPropertyAccess);
4850 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4851 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4852 &ResultBuilder::IsMember);
4853 Results.EnterNewScope();
4854 AddedPropertiesSet AddedProperties;
4855 AddObjCProperties(CCContext, IFace, true,
4856 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4857 Results, IsBaseExprStatement,
4858 /*IsClassProperty=*/true);
4859 Results.ExitScope();
4860 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4861 Results.data(), Results.size());
4862}
4863
Faisal Vali090da2d2018-01-01 18:23:28 +00004864void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004865 if (!CodeCompleter)
4866 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004867
4868 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004869 enum CodeCompletionContext::Kind ContextKind =
4870 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004871 switch ((DeclSpec::TST)TagSpec) {
4872 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004873 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004874 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004875 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004876
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004877 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004878 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004879 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004880 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004881
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004882 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004883 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004884 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004885 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004886 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004887 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004888
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004889 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004890 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004891 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004892
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004893 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4894 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004895 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004896
4897 // First pass: look for tags.
4898 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004899 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004900 CodeCompleter->includeGlobals(),
4901 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004902
Douglas Gregor39982192010-08-15 06:18:01 +00004903 if (CodeCompleter->includeGlobals()) {
4904 // Second pass: look for nested name specifiers.
4905 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004906 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4907 CodeCompleter->includeGlobals(),
4908 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004909 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004910
Douglas Gregor0ac41382010-09-23 23:01:17 +00004911 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004912 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004913}
4914
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004915static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4916 const LangOptions &LangOpts) {
4917 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4918 Results.AddResult("const");
4919 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4920 Results.AddResult("volatile");
4921 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4922 Results.AddResult("restrict");
4923 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4924 Results.AddResult("_Atomic");
4925 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4926 Results.AddResult("__unaligned");
4927}
4928
Douglas Gregor28c78432010-08-27 17:35:51 +00004929void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004930 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004931 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004932 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004933 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004934 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004935 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004936 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004937 Results.data(), Results.size());
4938}
4939
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004940void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4941 const VirtSpecifiers *VS) {
4942 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4943 CodeCompleter->getCodeCompletionTUInfo(),
4944 CodeCompletionContext::CCC_TypeQualifiers);
4945 Results.EnterNewScope();
4946 AddTypeQualifierResults(DS, Results, LangOpts);
4947 if (LangOpts.CPlusPlus11) {
4948 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004949 if (D.getContext() == DeclaratorContext::MemberContext &&
4950 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004951 if (!VS || !VS->isFinalSpecified())
4952 Results.AddResult("final");
4953 if (!VS || !VS->isOverrideSpecified())
4954 Results.AddResult("override");
4955 }
4956 }
4957 Results.ExitScope();
4958 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4959 Results.data(), Results.size());
4960}
4961
Benjamin Kramer72dae622016-02-18 15:30:24 +00004962void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4963 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4964}
4965
Douglas Gregord328d572009-09-21 18:10:23 +00004966void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004967 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004968 return;
John McCall5939b162011-08-06 07:30:58 +00004969
Richard Smithef6c43d2018-07-26 18:41:30 +00004970 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004971 // Condition expression might be invalid, do not continue in this case.
4972 if (!Switch->getCond())
4973 return;
John McCall5939b162011-08-06 07:30:58 +00004974 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4975 if (!type->isEnumeralType()) {
4976 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004977 Data.IntegralConstantExpression = true;
4978 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004979 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004980 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004981
Douglas Gregord328d572009-09-21 18:10:23 +00004982 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004983 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004984 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004985 if (EnumDecl *Def = Enum->getDefinition())
4986 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004987
Douglas Gregord328d572009-09-21 18:10:23 +00004988 // Determine which enumerators we have already seen in the switch statement.
4989 // FIXME: Ideally, we would also be able to look *past* the code-completion
4990 // token, in case we are code-completing in the middle of the switch and not
4991 // at the end. However, we aren't able to do so at the moment.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004992 CoveredEnumerators Enumerators;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004993 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004994 SC = SC->getNextSwitchCase()) {
4995 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4996 if (!Case)
4997 continue;
4998
4999 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00005000 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
5001 if (auto *Enumerator =
5002 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005003 // We look into the AST of the case statement to determine which
5004 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00005005 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005006 // values of each enumerator. However, value-based approach would not
5007 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00005008 // template are type- and value-dependent.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005009 Enumerators.Seen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005010
Douglas Gregorf2510672009-09-21 19:57:38 +00005011 // If this is a qualified-id, keep track of the nested-name-specifier
5012 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00005013 //
5014 // switch (TagD.getKind()) {
5015 // case TagDecl::TK_enum:
5016 // break;
5017 // case XXX
5018 //
Douglas Gregorf2510672009-09-21 19:57:38 +00005019 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00005020 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
5021 // TK_struct, and TK_class.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005022 Enumerators.SuggestedQualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00005023 }
5024 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005025
Douglas Gregord328d572009-09-21 18:10:23 +00005026 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005027 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005028 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005029 CodeCompletionContext::CCC_Expression);
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005030 AddEnumerators(Results, Context, Enum, CurContext, Enumerators);
Douglas Gregor285560922010-04-06 20:02:15 +00005031
Douglas Gregor21325842011-07-07 16:03:39 +00005032 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00005033 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00005034 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00005035 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5036 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00005037}
5038
Robert Wilhelm16e94b92013-08-09 18:02:13 +00005039static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005040 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005041 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005042
5043 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005044 if (!Args[I])
5045 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005046
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005047 return false;
5048}
5049
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005050typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
5051
Fangrui Song050229d2018-11-24 00:14:31 +00005052static void mergeCandidatesWithResults(
5053 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
5054 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Fangrui Song899d1392019-04-24 14:43:05 +00005055 // Sort the overload candidate set by placing the best overloads first.
5056 llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
5057 const OverloadCandidate &Y) {
5058 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
5059 CandidateSet.getKind());
5060 });
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005061
Fangrui Song899d1392019-04-24 14:43:05 +00005062 // Add the remaining viable overload candidates as code-completion results.
5063 for (OverloadCandidate &Candidate : CandidateSet) {
5064 if (Candidate.Function && Candidate.Function->isDeleted())
5065 continue;
5066 if (Candidate.Viable)
5067 Results.push_back(ResultCandidate(Candidate.Function));
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005068 }
5069}
5070
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005071/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005072/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00005073static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00005074 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005075
5076 // Given the overloads 'Candidates' for a function call matching all arguments
5077 // up to N, return the type of the Nth parameter if it is the same for all
5078 // overload candidates.
5079 QualType ParamType;
5080 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00005081 if (const auto *FType = Candidate.getFunctionType())
5082 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005083 if (N < Proto->getNumParams()) {
5084 if (ParamType.isNull())
5085 ParamType = Proto->getParamType(N);
5086 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00005087 ParamType.getNonReferenceType(),
5088 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005089 // Otherwise return a default-constructed QualType.
5090 return QualType();
5091 }
5092 }
5093
5094 return ParamType;
5095}
5096
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005097static QualType
5098ProduceSignatureHelp(Sema &SemaRef, Scope *S,
5099 MutableArrayRef<ResultCandidate> Candidates,
5100 unsigned CurrentArg, SourceLocation OpenParLoc) {
5101 if (Candidates.empty())
5102 return QualType();
5103 SemaRef.CodeCompleter->ProcessOverloadCandidates(
5104 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
5105 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005106}
5107
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005108QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
5109 ArrayRef<Expr *> Args,
5110 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00005111 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005112 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005113
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005114 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00005115 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005116 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
5117 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005118 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005119 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005120
John McCall57500772009-12-16 12:17:52 +00005121 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00005122 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00005123 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00005124
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005125 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00005126
John McCall57500772009-12-16 12:17:52 +00005127 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005128 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005129 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005130 /*PartialOverloading=*/true);
5131 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
5132 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
5133 if (UME->hasExplicitTemplateArgs()) {
5134 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
5135 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00005136 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00005137
5138 // Add the base as first argument (use a nullptr if the base is implicit).
5139 SmallVector<Expr *, 12> ArgExprs(
5140 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005141 ArgExprs.append(Args.begin(), Args.end());
5142 UnresolvedSet<8> Decls;
5143 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00005144 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005145 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005146 /*SuppressUserConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00005147 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005148 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005149 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00005150 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005151 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00005152 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005153 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005154 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00005155 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005156 !FD->getType()->getAs<FunctionProtoType>())
5157 Results.push_back(ResultCandidate(FD));
5158 else
5159 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
5160 Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005161 /*SuppressUserConversions=*/false,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005162 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005163
5164 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
5165 // If expression's type is CXXRecordDecl, it may overload the function
5166 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005167 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00005168 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00005169 DeclarationName OpName =
5170 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005171 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
5172 LookupQualifiedName(R, DC);
5173 R.suppressDiagnostics();
5174 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
5175 ArgExprs.append(Args.begin(), Args.end());
5176 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
5177 /*ExplicitArgs=*/nullptr,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005178 /*SuppressUserConversions=*/false,
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005179 /*PartialOverloading=*/true);
5180 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005181 } else {
5182 // Lastly we check whether expression's type is function pointer or
5183 // function.
5184 QualType T = NakedFn->getType();
5185 if (!T->getPointeeType().isNull())
5186 T = T->getPointeeType();
5187
5188 if (auto FP = T->getAs<FunctionProtoType>()) {
5189 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00005190 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005191 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005192 Results.push_back(ResultCandidate(FP));
5193 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005194 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005195 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005196 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005197 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005198 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005199 QualType ParamType =
5200 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
5201 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005202}
5203
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005204QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
5205 SourceLocation Loc,
5206 ArrayRef<Expr *> Args,
5207 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005208 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005209 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005210
5211 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00005212 CXXRecordDecl *RD =
5213 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005214 if (!RD)
5215 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00005216
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005217 // FIXME: Provide support for member initializers.
5218 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005219
5220 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
5221
Fangrui Song050229d2018-11-24 00:14:31 +00005222 for (NamedDecl *C : LookupConstructors(RD)) {
5223 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
5224 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
5225 CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005226 /*SuppressUserConversions=*/false,
Richard Smith76b90272019-05-09 03:59:21 +00005227 /*PartialOverloading=*/true,
5228 /*AllowExplicit*/ true);
Fangrui Song050229d2018-11-24 00:14:31 +00005229 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
5230 AddTemplateOverloadCandidate(
5231 FTD, DeclAccessPair::make(FTD, C->getAccess()),
5232 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005233 /*SuppressUserConversions=*/false,
Hans Wennborgd2b9fc82019-05-06 09:51:10 +00005234 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005235 }
5236 }
5237
5238 SmallVector<ResultCandidate, 8> Results;
5239 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005240 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00005241}
5242
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00005243QualType Sema::ProduceCtorInitMemberSignatureHelp(
5244 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
5245 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
5246 if (!CodeCompleter)
5247 return QualType();
5248
5249 CXXConstructorDecl *Constructor =
5250 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
5251 if (!Constructor)
5252 return QualType();
5253 // FIXME: Add support for Base class constructors as well.
5254 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
5255 Constructor->getParent(), SS, TemplateTypeTy, II))
5256 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
5257 MemberDecl->getLocation(), ArgExprs,
5258 OpenParLoc);
5259 return QualType();
5260}
5261
John McCall48871652010-08-21 09:40:31 +00005262void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
5263 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005264 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005265 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005266 return;
5267 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005268
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005269 CodeCompleteExpressionData Data;
5270 Data.PreferredType = VD->getType();
5271 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5272 Data.IgnoreDecls.push_back(VD);
5273
5274 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005275}
5276
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005277void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005278 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005279 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005280 mapCodeCompletionContext(*this, PCC_Statement));
5281 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5282 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005283
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005284 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5285 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005286 CodeCompleter->includeGlobals(),
5287 CodeCompleter->loadExternal());
5288
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005289 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005290
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005291 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005292 CodeCompletionBuilder Builder(Results.getAllocator(),
5293 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005294 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005295 if (Results.includeCodePatterns()) {
5296 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5297 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5298 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5299 Builder.AddPlaceholderChunk("statements");
5300 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5301 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5302 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005303 Results.AddResult(Builder.TakeString());
5304
5305 // "else if" block
Ilya Biryukov30977fc2019-06-04 09:26:08 +00005306 Builder.AddTypedTextChunk("else if");
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005307 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5308 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005309 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005310 Builder.AddPlaceholderChunk("condition");
5311 else
5312 Builder.AddPlaceholderChunk("expression");
5313 Builder.AddChunk(CodeCompletionString::CK_RightParen);
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 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005325
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005326 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005327 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005328
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005329 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005330 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005331
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005332 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005333 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005334}
5335
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005336void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005337 bool EnteringContext,
5338 bool IsUsingDeclaration, QualType BaseType,
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005339 QualType PreferredType) {
Eric Liu06d34022017-12-12 11:35:46 +00005340 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005341 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005342
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005343 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType);
5344 CC.setIsUsingDeclaration(IsUsingDeclaration);
5345 CC.setCXXScopeSpecifier(SS);
5346
Eric Liu06d34022017-12-12 11:35:46 +00005347 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5348 // "a::b::" is not corresponding to any context/namespace in the AST), since
5349 // it can be useful for global code completion which have information about
5350 // contexts/symbols that are not in the AST.
5351 if (SS.isInvalid()) {
Eric Liu206740e2019-02-21 11:22:58 +00005352 // As SS is invalid, we try to collect accessible contexts from the current
5353 // scope with a dummy lookup so that the completion consumer can try to
5354 // guess what the specified scope is.
5355 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5356 CodeCompleter->getCodeCompletionTUInfo(), CC);
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005357 if (!PreferredType.isNull())
5358 DummyResults.setPreferredType(PreferredType);
Eric Liu206740e2019-02-21 11:22:58 +00005359 if (S->getEntity()) {
5360 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5361 BaseType);
5362 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5363 /*IncludeGlobalScope=*/false,
5364 /*LoadExternal=*/false);
5365 }
5366 HandleCodeCompleteResults(this, CodeCompleter,
5367 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005368 return;
5369 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005370 // Always pretend to enter a context to ensure that a dependent type
5371 // resolves to a dependent record.
5372 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005373 if (!Ctx)
5374 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005375
5376 // Try to instantiate any non-dependent declaration contexts before
5377 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005378 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005379 return;
5380
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005381 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5382 CodeCompleter->getCodeCompletionTUInfo(), CC);
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005383 if (!PreferredType.isNull())
5384 Results.setPreferredType(PreferredType);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005385 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005386
Douglas Gregor3545ff42009-09-21 16:56:56 +00005387 // The "template" keyword can follow "::" in the grammar, but only
5388 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005389 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005390 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005391 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005392
5393 // Add calls to overridden virtual functions, if there are any.
5394 //
5395 // FIXME: This isn't wonderful, because we don't know whether we're actually
5396 // in a context that permits expressions. This is a general issue with
5397 // qualified-id completions.
5398 if (!EnteringContext)
5399 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005400 Results.ExitScope();
5401
Eric Liufead6ae2017-12-13 10:26:49 +00005402 if (CodeCompleter->includeNamespaceLevelDecls() ||
5403 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005404 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005405 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5406 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005407 /*IncludeDependentBases=*/true,
5408 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005409 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005410
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005411 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5412 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005413}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005414
5415void Sema::CodeCompleteUsing(Scope *S) {
5416 if (!CodeCompleter)
5417 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005418
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005419 // This can be both a using alias or using declaration, in the former we
5420 // expect a new name and a symbol in the latter case.
5421 CodeCompletionContext Context(CodeCompletionContext::CCC_SymbolOrNewName);
5422 Context.setIsUsingDeclaration(true);
5423
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005424 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ilya Biryukovd9971d02019-10-28 09:34:21 +01005425 CodeCompleter->getCodeCompletionTUInfo(), Context,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005426 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005427 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005428
Douglas Gregor3545ff42009-09-21 16:56:56 +00005429 // If we aren't in class scope, we could see the "namespace" keyword.
5430 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005431 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005432
5433 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005434 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005435 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005436 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005437 CodeCompleter->includeGlobals(),
5438 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005439 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005440
5441 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5442 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005443}
5444
5445void Sema::CodeCompleteUsingDirective(Scope *S) {
5446 if (!CodeCompleter)
5447 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005448
Douglas Gregor3545ff42009-09-21 16:56:56 +00005449 // After "using namespace", we expect to see a namespace name or namespace
5450 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005451 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005452 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005453 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005454 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005455 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005456 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005457 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005458 CodeCompleter->includeGlobals(),
5459 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005460 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005461 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5462 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005463}
5464
Fangrui Song050229d2018-11-24 00:14:31 +00005465void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005466 if (!CodeCompleter)
5467 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005468
Ted Kremenekc37877d2013-10-08 17:08:03 +00005469 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005470 if (!S->getParent())
5471 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005472
Fangrui Song050229d2018-11-24 00:14:31 +00005473 bool SuppressedGlobalResults =
5474 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005475
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005476 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005477 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005478 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005479 ? CodeCompletionContext::CCC_Namespace
5480 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005481 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005482
Douglas Gregor0ac41382010-09-23 23:01:17 +00005483 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005484 // We only want to see those namespaces that have already been defined
5485 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005486 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005487 // definition of each namespace.
5488 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005489 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005490 NS(Ctx->decls_begin()),
5491 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005492 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005493 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005494
5495 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005496 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005497 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005498 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005499 NS = OrigToLatest.begin(),
5500 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005501 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005502 Results.AddResult(
5503 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5504 nullptr),
5505 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005506 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005507 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005508
Fangrui Song050229d2018-11-24 00:14:31 +00005509 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5510 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005511}
5512
Fangrui Song050229d2018-11-24 00:14:31 +00005513void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005514 if (!CodeCompleter)
5515 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005516
Douglas Gregor3545ff42009-09-21 16:56:56 +00005517 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005518 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005519 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005520 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005521 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005522 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005523 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005524 CodeCompleter->includeGlobals(),
5525 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005526 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5527 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005528}
5529
Douglas Gregorc811ede2009-09-18 20:05:18 +00005530void Sema::CodeCompleteOperatorName(Scope *S) {
5531 if (!CodeCompleter)
5532 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005533
John McCall276321a2010-08-25 06:19:51 +00005534 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005535 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005536 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005537 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005538 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005539 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005540
Richard Smith7fa2b742019-06-14 20:01:51 +00005541 // Add the names of overloadable operators. Note that OO_Conditional is not
5542 // actually overloadable.
Fangrui Song050229d2018-11-24 00:14:31 +00005543#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
Richard Smith7fa2b742019-06-14 20:01:51 +00005544 if (OO_##Name != OO_Conditional) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005545 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005546#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005547
Douglas Gregor3545ff42009-09-21 16:56:56 +00005548 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005549 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005550 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005551 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005552 CodeCompleter->includeGlobals(),
5553 CodeCompleter->loadExternal());
5554
Douglas Gregor3545ff42009-09-21 16:56:56 +00005555 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005556 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005557 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005558
5559 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5560 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005561}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005562
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005563void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005564 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005565 if (!ConstructorD)
5566 return;
5567
5568 AdjustDeclIfTemplate(ConstructorD);
5569
Fangrui Song050229d2018-11-24 00:14:31 +00005570 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005571 if (!Constructor)
5572 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005573
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005574 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005575 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005576 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005577 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005578
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005579 // Fill in any already-initialized fields or base classes.
5580 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5581 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005582 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005583 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005584 InitializedBases.insert(Context.getCanonicalType(
5585 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005586 else
Fangrui Song050229d2018-11-24 00:14:31 +00005587 InitializedFields.insert(
5588 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005589 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005590
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005591 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005592 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005593 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005594 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005595
5596 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5597 CodeCompletionBuilder Builder(Results.getAllocator(),
5598 Results.getCodeCompletionTUInfo());
5599 Builder.AddTypedTextChunk(Name);
5600 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005601 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005602 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005603 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005604 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5605 Builder);
5606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5607 return Builder.TakeString();
5608 };
5609 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5610 const NamedDecl *ND) {
5611 CodeCompletionBuilder Builder(Results.getAllocator(),
5612 Results.getCodeCompletionTUInfo());
5613 Builder.AddTypedTextChunk(Name);
5614 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5615 Builder.AddPlaceholderChunk(Type);
5616 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5617 if (ND) {
5618 auto CCR = CodeCompletionResult(
5619 Builder.TakeString(), ND,
5620 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5621 if (isa<FieldDecl>(ND))
5622 CCR.CursorKind = CXCursor_MemberRef;
5623 return Results.AddResult(CCR);
5624 }
5625 return Results.AddResult(CodeCompletionResult(
5626 Builder.TakeString(),
5627 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5628 };
5629 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5630 const char *Name, const FieldDecl *FD) {
5631 if (!RD)
5632 return AddDefaultCtorInit(Name,
5633 FD ? Results.getAllocator().CopyString(
5634 FD->getType().getAsString(Policy))
5635 : Name,
5636 FD);
5637 auto Ctors = getConstructors(Context, RD);
5638 if (Ctors.begin() == Ctors.end())
5639 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005640 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005641 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5642 CCR.CursorKind = getCursorKindForDecl(Ctor);
5643 Results.AddResult(CCR);
5644 }
5645 };
5646 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5647 const char *BaseName =
5648 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5649 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5650 AddCtorsWithName(
5651 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5652 BaseName, nullptr);
5653 };
5654 auto AddField = [&](const FieldDecl *FD) {
5655 const char *FieldName =
5656 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5657 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5658 AddCtorsWithName(
5659 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5660 FieldName, FD);
5661 };
5662
Aaron Ballman574705e2014-03-13 15:41:46 +00005663 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005664 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5665 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005666 SawLastInitializer =
5667 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5668 Context.hasSameUnqualifiedType(
5669 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005670 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005671 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005672
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005673 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005674 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005675 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005676
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005677 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005678 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005679 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5680 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005681 SawLastInitializer =
5682 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5683 Context.hasSameUnqualifiedType(
5684 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005685 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005686 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005687
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005688 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005689 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005690 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005691
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005692 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005693 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005694 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5695 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005696 SawLastInitializer = !Initializers.empty() &&
5697 Initializers.back()->isAnyMemberInitializer() &&
5698 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005699 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005700 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005701
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005702 if (!Field->getDeclName())
5703 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005704
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005705 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005706 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005707 }
5708 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005709
Douglas Gregor0ac41382010-09-23 23:01:17 +00005710 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005711 Results.data(), Results.size());
5712}
5713
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005714/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005715static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005716 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005717 if (!DC)
5718 return false;
5719
5720 return DC->isFileContext();
5721}
5722
5723void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5724 bool AfterAmpersand) {
5725 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005726 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005727 CodeCompletionContext::CCC_Other);
5728 Results.EnterNewScope();
5729
5730 // Note what has already been captured.
5731 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5732 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005733 for (const auto &C : Intro.Captures) {
5734 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005735 IncludedThis = true;
5736 continue;
5737 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005738
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005739 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005740 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005741
Douglas Gregord8c61782012-02-15 15:34:24 +00005742 // Look for other capturable variables.
5743 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005744 for (const auto *D : S->decls()) {
5745 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005746 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005747 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005748
David Blaikie82e95a32014-11-19 07:49:47 +00005749 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005750 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005751 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005752 }
5753 }
5754
5755 // Add 'this', if it would be valid.
5756 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5757 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005758
Douglas Gregord8c61782012-02-15 15:34:24 +00005759 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005760
Douglas Gregord8c61782012-02-15 15:34:24 +00005761 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5762 Results.data(), Results.size());
5763}
5764
James Dennett596e4752012-06-14 03:11:41 +00005765/// Macro that optionally prepends an "@" to the string literal passed in via
5766/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005767#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005768
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005769static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005770 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005771 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005772 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005773 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005774
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005775 CodeCompletionBuilder Builder(Results.getAllocator(),
5776 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005777 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005778 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005779 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005780 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5781 Builder.AddPlaceholderChunk("property");
5782 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005783
Douglas Gregorf1934162010-01-13 21:24:21 +00005784 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005785 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005786 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5787 Builder.AddPlaceholderChunk("property");
5788 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005789 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005790}
5791
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005792static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005793 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005794 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005795
Douglas Gregorf1934162010-01-13 21:24:21 +00005796 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005797 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005798
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005799 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005800 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005801 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005802
Douglas Gregorf1934162010-01-13 21:24:21 +00005803 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005804 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005805
Douglas Gregorf1934162010-01-13 21:24:21 +00005806 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005807 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005808 }
5809}
5810
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005811static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005812 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005813 CodeCompletionBuilder Builder(Results.getAllocator(),
5814 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005815
Douglas Gregorf1934162010-01-13 21:24:21 +00005816 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005817 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005818 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5819 Builder.AddPlaceholderChunk("name");
5820 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005821
Douglas Gregorf4c33342010-05-28 00:22:41 +00005822 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005823 // @interface name
5824 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005825 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005826 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005827 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5828 Builder.AddPlaceholderChunk("class");
5829 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005830
Douglas Gregorf4c33342010-05-28 00:22:41 +00005831 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005832 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005833 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5834 Builder.AddPlaceholderChunk("protocol");
5835 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005836
Douglas Gregorf4c33342010-05-28 00:22:41 +00005837 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005838 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005839 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5840 Builder.AddPlaceholderChunk("class");
5841 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005842 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005843
Douglas Gregorf1934162010-01-13 21:24:21 +00005844 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005845 Builder.AddTypedTextChunk(
5846 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005847 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5848 Builder.AddPlaceholderChunk("alias");
5849 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5850 Builder.AddPlaceholderChunk("class");
5851 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005852
5853 if (Results.getSema().getLangOpts().Modules) {
5854 // @import name
5855 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5857 Builder.AddPlaceholderChunk("module");
5858 Results.AddResult(Result(Builder.TakeString()));
5859 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005860}
5861
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005862void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005863 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005864 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005865 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005866 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005867 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005868 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005869 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005870 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005871 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005872 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005873 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005874 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5875 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005876}
5877
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005878static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005879 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005880 CodeCompletionBuilder Builder(Results.getAllocator(),
5881 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005882
5883 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005884 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005885 if (Results.getSema().getLangOpts().CPlusPlus ||
5886 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005887 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005888 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005889 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005890 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5891 Builder.AddPlaceholderChunk("type-name");
5892 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5893 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005894
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005895 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005896 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005897 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005898 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5899 Builder.AddPlaceholderChunk("protocol-name");
5900 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5901 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005902
5903 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005904 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005905 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005906 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5907 Builder.AddPlaceholderChunk("selector");
5908 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5909 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005910
5911 // @"string"
5912 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005913 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005914 Builder.AddPlaceholderChunk("string");
5915 Builder.AddTextChunk("\"");
5916 Results.AddResult(Result(Builder.TakeString()));
5917
Douglas Gregor951de302012-07-17 23:24:47 +00005918 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005919 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005920 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005921 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005922 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5923 Results.AddResult(Result(Builder.TakeString()));
5924
Douglas Gregor951de302012-07-17 23:24:47 +00005925 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005926 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005927 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005928 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005929 Builder.AddChunk(CodeCompletionString::CK_Colon);
5930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5931 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005932 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5933 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005934
Douglas Gregor951de302012-07-17 23:24:47 +00005935 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005936 Builder.AddResultTypeChunk("id");
5937 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005938 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005939 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5940 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005941}
5942
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005943static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005944 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005945 CodeCompletionBuilder Builder(Results.getAllocator(),
5946 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005947
Douglas Gregorf4c33342010-05-28 00:22:41 +00005948 if (Results.includeCodePatterns()) {
5949 // @try { statements } @catch ( declaration ) { statements } @finally
5950 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005951 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005952 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5953 Builder.AddPlaceholderChunk("statements");
5954 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5955 Builder.AddTextChunk("@catch");
5956 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5957 Builder.AddPlaceholderChunk("parameter");
5958 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5959 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5960 Builder.AddPlaceholderChunk("statements");
5961 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5962 Builder.AddTextChunk("@finally");
5963 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5964 Builder.AddPlaceholderChunk("statements");
5965 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5966 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005967 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005968
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005969 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005970 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005971 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5972 Builder.AddPlaceholderChunk("expression");
5973 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005974
Douglas Gregorf4c33342010-05-28 00:22:41 +00005975 if (Results.includeCodePatterns()) {
5976 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005977 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5979 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5980 Builder.AddPlaceholderChunk("expression");
5981 Builder.AddChunk(CodeCompletionString::CK_RightParen);
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 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005987}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005988
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005989static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005990 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005991 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005992 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5993 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5994 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005995 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005996 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005997}
5998
5999void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006000 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006001 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006002 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00006003 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00006004 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00006005 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006006 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6007 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00006008}
6009
6010void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006011 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006012 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006013 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00006014 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006015 AddObjCStatementResults(Results, false);
6016 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006017 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006018 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6019 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006020}
6021
6022void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006023 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006024 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006025 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006026 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006027 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006028 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006029 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6030 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006031}
6032
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006033/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00006034/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00006035static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00006036 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00006037 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00006038 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006039
Bill Wendling44426052012-12-20 19:22:21 +00006040 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006041
Douglas Gregore6078da2009-11-19 00:14:45 +00006042 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00006043 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
6044 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00006045 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006046
Jordan Rose53cb2f32012-08-20 20:01:13 +00006047 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00006048 unsigned AssignCopyRetMask =
6049 Attributes &
6050 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
6051 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
6052 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
6053 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00006054 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00006055 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00006056 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00006057 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
6058 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00006059 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006060
Douglas Gregore6078da2009-11-19 00:14:45 +00006061 return false;
6062}
6063
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006064void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00006065 if (!CodeCompleter)
6066 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006067
Bill Wendling44426052012-12-20 19:22:21 +00006068 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006069
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006070 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006071 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006072 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00006073 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00006074 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00006075 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00006076 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00006077 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00006078 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00006079 ObjCDeclSpec::DQ_PR_unsafe_unretained))
6080 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00006081 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00006082 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00006083 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00006084 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00006085 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00006086 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00006087 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00006088 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00006089 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00006090 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00006091 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00006092 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00006093
6094 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00006095 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00006096 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00006097 Results.AddResult(CodeCompletionResult("weak"));
6098
Bill Wendling44426052012-12-20 19:22:21 +00006099 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006100 CodeCompletionBuilder Setter(Results.getAllocator(),
6101 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006102 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006103 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006104 Setter.AddPlaceholderChunk("method");
6105 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006106 }
Bill Wendling44426052012-12-20 19:22:21 +00006107 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006108 CodeCompletionBuilder Getter(Results.getAllocator(),
6109 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006110 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006111 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006112 Getter.AddPlaceholderChunk("method");
6113 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006114 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006115 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
6116 Results.AddResult(CodeCompletionResult("nonnull"));
6117 Results.AddResult(CodeCompletionResult("nullable"));
6118 Results.AddResult(CodeCompletionResult("null_unspecified"));
6119 Results.AddResult(CodeCompletionResult("null_resettable"));
6120 }
Steve Naroff936354c2009-10-08 21:55:05 +00006121 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006122 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6123 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00006124}
Steve Naroffeae65032009-11-07 02:08:14 +00006125
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006126/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00006127/// via code completion.
6128enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00006129 MK_Any, ///< Any kind of method, provided it means other specified criteria.
6130 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00006131 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006132};
6133
Fangrui Song050229d2018-11-24 00:14:31 +00006134static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006135 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006136 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006137 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006138 if (NumSelIdents > Sel.getNumArgs())
6139 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006140
Douglas Gregor67c692c2010-08-26 15:07:07 +00006141 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00006142 case MK_Any:
6143 break;
6144 case MK_ZeroArgSelector:
6145 return Sel.isUnarySelector();
6146 case MK_OneArgSelector:
6147 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006148 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006149
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006150 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
6151 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006152
Douglas Gregor67c692c2010-08-26 15:07:07 +00006153 for (unsigned I = 0; I != NumSelIdents; ++I)
6154 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
6155 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006156
Douglas Gregor67c692c2010-08-26 15:07:07 +00006157 return true;
6158}
6159
Douglas Gregorc8537c52009-11-19 07:41:15 +00006160static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
6161 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006162 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006163 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006164 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006165 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006166}
Douglas Gregor1154e272010-09-16 16:06:31 +00006167
Fangrui Song050229d2018-11-24 00:14:31 +00006168/// A set of selectors, which is used to avoid introducing multiple
6169/// completions with the same selector into the result set.
6170typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00006171
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006172/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006173/// container to the set of results.
6174///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006175/// The container will be a class, protocol, category, or implementation of
6176/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006177/// the superclasses of classes along with their categories, protocols, and
6178/// implementations.
6179///
6180/// \param Container the container in which we'll look to find methods.
6181///
James Dennett596e4752012-06-14 03:11:41 +00006182/// \param WantInstanceMethods Whether to add instance methods (only); if
6183/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006184///
6185/// \param CurContext the context in which we're performing the lookup that
6186/// finds methods.
6187///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006188/// \param AllowSameLength Whether we allow a method to be added to the list
6189/// when it has the same number of parameters as we have selector identifiers.
6190///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006191/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006192static void AddObjCMethods(ObjCContainerDecl *Container,
6193 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006194 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006195 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006196 VisitedSelectorSet &Selectors, bool AllowSameLength,
6197 ResultBuilder &Results, bool InOriginalClass = true,
6198 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00006199 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006200 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00006201 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00006202 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00006203 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00006204 // The instance methods on the root class can be messaged via the
6205 // metaclass.
6206 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00006207 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006208 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00006209 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006210 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00006211 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00006212
David Blaikie82e95a32014-11-19 07:49:47 +00006213 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006214 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006215
6216 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006217 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00006218 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00006219 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00006220 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00006221 Results.MaybeAddResult(R, CurContext);
6222 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006223 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006224
Douglas Gregorf37c9492010-09-16 15:34:59 +00006225 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006226 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00006227 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006228 const ObjCList<ObjCProtocolDecl> &Protocols =
6229 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006230 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006231 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006232 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006233 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6234 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00006235 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00006236 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006237
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006238 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006239 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006240
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006241 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006242 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006243 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6244 Selectors, AllowSameLength, Results, false, IsRootClass);
6245
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006246 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00006247 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006248 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006249 CurContext, Selectors, AllowSameLength, Results,
6250 InOriginalClass, IsRootClass);
6251
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006252 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00006253 const ObjCList<ObjCProtocolDecl> &Protocols =
6254 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006255 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6256 E = Protocols.end();
6257 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006258 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6259 Selectors, AllowSameLength, Results, false, IsRootClass);
6260
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006261 // Add methods in category implementations.
6262 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006263 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6264 Selectors, AllowSameLength, Results, InOriginalClass,
6265 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006266 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006267
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006268 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006269 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006270 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006271 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6272 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6273 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006274
6275 // Add methods in our implementation, if any.
6276 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006277 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6278 Selectors, AllowSameLength, Results, InOriginalClass,
6279 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006280}
6281
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006282void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006283 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006284 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006285 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006286 if (ObjCCategoryDecl *Category =
6287 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006288 Class = Category->getClassInterface();
6289
6290 if (!Class)
6291 return;
6292 }
6293
6294 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006295 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006296 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006297 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006298 Results.EnterNewScope();
6299
Douglas Gregor1154e272010-09-16 16:06:31 +00006300 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006301 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006302 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006303 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006304 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6305 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006306}
6307
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006308void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006309 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006310 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006311 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006312 if (ObjCCategoryDecl *Category =
6313 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006314 Class = Category->getClassInterface();
6315
6316 if (!Class)
6317 return;
6318 }
6319
6320 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006321 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006322 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006323 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006324 Results.EnterNewScope();
6325
Douglas Gregor1154e272010-09-16 16:06:31 +00006326 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006327 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6328 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006329
6330 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006331 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6332 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006333}
6334
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006335void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6336 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006337 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006338 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006339 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006340 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006341
Douglas Gregor99fa2642010-08-24 01:06:58 +00006342 // Add context-sensitive, Objective-C parameter-passing keywords.
6343 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006344 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006345 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6346 Results.AddResult("in");
6347 Results.AddResult("inout");
6348 AddedInOut = true;
6349 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006350 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006351 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6352 Results.AddResult("out");
6353 if (!AddedInOut)
6354 Results.AddResult("inout");
6355 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006356 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006357 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6358 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006359 Results.AddResult("bycopy");
6360 Results.AddResult("byref");
6361 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006362 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006363 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6364 Results.AddResult("nonnull");
6365 Results.AddResult("nullable");
6366 Results.AddResult("null_unspecified");
6367 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006368
6369 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006370 // identifier IBAction refers to a macro, provide a completion item for
6371 // an action, e.g.,
6372 // IBAction)<#selector#>:(id)sender
6373 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006374 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006375 CodeCompletionBuilder Builder(Results.getAllocator(),
6376 Results.getCodeCompletionTUInfo(),
6377 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006378 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006379 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006380 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006381 Builder.AddChunk(CodeCompletionString::CK_Colon);
6382 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006383 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006384 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006385 Builder.AddTextChunk("sender");
6386 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6387 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006388
6389 // If we're completing the return type, provide 'instancetype'.
6390 if (!IsParameter) {
6391 Results.AddResult(CodeCompletionResult("instancetype"));
6392 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006393
Douglas Gregor99fa2642010-08-24 01:06:58 +00006394 // Add various builtin type names and specifiers.
6395 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6396 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006397
Douglas Gregor99fa2642010-08-24 01:06:58 +00006398 // Add the various type names
6399 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6400 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6401 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006402 CodeCompleter->includeGlobals(),
6403 CodeCompleter->loadExternal());
6404
Douglas Gregor99fa2642010-08-24 01:06:58 +00006405 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006406 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006407
Eric Liuf5ba09f2018-07-04 10:01:18 +00006408 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006409 Results.data(), Results.size());
6410}
6411
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006412/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006413/// that it has some more-specific class type based on knowledge of
6414/// common uses of Objective-C. This routine returns that class type,
6415/// or NULL if no better result could be determined.
6416static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006417 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006418 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006419 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006420
6421 Selector Sel = Msg->getSelector();
6422 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006423 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006424
6425 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6426 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006427 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006428
6429 ObjCMethodDecl *Method = Msg->getMethodDecl();
6430 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006431 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006432
6433 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006434 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006435 switch (Msg->getReceiverKind()) {
6436 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006437 if (const ObjCObjectType *ObjType =
6438 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006439 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006440 break;
6441
6442 case ObjCMessageExpr::Instance: {
6443 QualType T = Msg->getInstanceReceiver()->getType();
6444 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6445 IFace = Ptr->getInterfaceDecl();
6446 break;
6447 }
6448
6449 case ObjCMessageExpr::SuperInstance:
6450 case ObjCMessageExpr::SuperClass:
6451 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006452 }
6453
6454 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006455 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006456
6457 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6458 if (Method->isInstanceMethod())
6459 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006460 .Case("retain", IFace)
6461 .Case("strong", IFace)
6462 .Case("autorelease", IFace)
6463 .Case("copy", IFace)
6464 .Case("copyWithZone", IFace)
6465 .Case("mutableCopy", IFace)
6466 .Case("mutableCopyWithZone", IFace)
6467 .Case("awakeFromCoder", IFace)
6468 .Case("replacementObjectFromCoder", IFace)
6469 .Case("class", IFace)
6470 .Case("classForCoder", IFace)
6471 .Case("superclass", Super)
6472 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006473
6474 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006475 .Case("new", IFace)
6476 .Case("alloc", IFace)
6477 .Case("allocWithZone", IFace)
6478 .Case("class", IFace)
6479 .Case("superclass", Super)
6480 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006481}
6482
Douglas Gregor6fc04132010-08-27 15:10:57 +00006483// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006484// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006485// function.
6486///
6487/// \param S The semantic analysis object.
6488///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006489/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006490/// the "super" keyword. Otherwise, we just need to provide the arguments.
6491///
6492/// \param SelIdents The identifiers in the selector that have already been
6493/// provided as arguments for a send to "super".
6494///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006495/// \param Results The set of results to augment.
6496///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006497/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006498/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006499static ObjCMethodDecl *
6500AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6501 ArrayRef<IdentifierInfo *> SelIdents,
6502 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006503 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6504 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006505 return nullptr;
6506
Douglas Gregor6fc04132010-08-27 15:10:57 +00006507 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6508 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006509 return nullptr;
6510
Douglas Gregor6fc04132010-08-27 15:10:57 +00006511 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006512 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006513 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6514 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006515 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006516 CurMethod->isInstanceMethod());
6517
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006518 // Check in categories or class extensions.
6519 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006520 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006521 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006522 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006523 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006524 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006525 }
6526 }
6527
Douglas Gregor6fc04132010-08-27 15:10:57 +00006528 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006529 return nullptr;
6530
Douglas Gregor6fc04132010-08-27 15:10:57 +00006531 // Check whether the superclass method has the same signature.
6532 if (CurMethod->param_size() != SuperMethod->param_size() ||
6533 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006534 return nullptr;
6535
Douglas Gregor6fc04132010-08-27 15:10:57 +00006536 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006537 CurPEnd = CurMethod->param_end(),
6538 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006539 CurP != CurPEnd; ++CurP, ++SuperP) {
6540 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006541 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006542 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006543 return nullptr;
6544
Douglas Gregor6fc04132010-08-27 15:10:57 +00006545 // Make sure we have a parameter name to forward!
6546 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006547 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006548 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006549
Douglas Gregor6fc04132010-08-27 15:10:57 +00006550 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006551 CodeCompletionBuilder Builder(Results.getAllocator(),
6552 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006553
Douglas Gregor6fc04132010-08-27 15:10:57 +00006554 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006555 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006556 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006557
6558 // If we need the "super" keyword, add it (plus some spacing).
6559 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006560 Builder.AddTypedTextChunk("super");
6561 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006562 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006563
Douglas Gregor6fc04132010-08-27 15:10:57 +00006564 Selector Sel = CurMethod->getSelector();
6565 if (Sel.isUnarySelector()) {
6566 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006567 Builder.AddTextChunk(
6568 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006569 else
Fangrui Song050229d2018-11-24 00:14:31 +00006570 Builder.AddTypedTextChunk(
6571 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006572 } else {
6573 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6574 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006575 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006576 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006577
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006578 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006579 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006580 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006581 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006582 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006583 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006584 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006585 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006586 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006587 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006588 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006589 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006590 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006591 }
6592 }
6593 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006594
Douglas Gregor78254c82012-03-27 23:34:16 +00006595 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6596 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006597 return SuperMethod;
6598}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006599
Douglas Gregora817a192010-05-27 23:06:34 +00006600void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006601 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006602 ResultBuilder Results(
6603 *this, CodeCompleter->getAllocator(),
6604 CodeCompleter->getCodeCompletionTUInfo(),
6605 CodeCompletionContext::CCC_ObjCMessageReceiver,
6606 getLangOpts().CPlusPlus11
6607 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6608 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006609
Douglas Gregora817a192010-05-27 23:06:34 +00006610 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6611 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006612 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006613 CodeCompleter->includeGlobals(),
6614 CodeCompleter->loadExternal());
6615
Douglas Gregora817a192010-05-27 23:06:34 +00006616 // If we are in an Objective-C method inside a class that has a superclass,
6617 // add "super" as an option.
6618 if (ObjCMethodDecl *Method = getCurMethodDecl())
6619 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006620 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006621 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006622
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006623 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006624 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006625
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006626 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006627 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006628
Douglas Gregora817a192010-05-27 23:06:34 +00006629 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006630
Douglas Gregora817a192010-05-27 23:06:34 +00006631 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006632 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006633 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006634 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006635}
6636
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006637void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006638 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006639 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006640 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006641 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6642 // Figure out which interface we're in.
6643 CDecl = CurMethod->getClassInterface();
6644 if (!CDecl)
6645 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006646
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006647 // Find the superclass of this class.
6648 CDecl = CDecl->getSuperClass();
6649 if (!CDecl)
6650 return;
6651
6652 if (CurMethod->isInstanceMethod()) {
6653 // We are inside an instance method, which means that the message
6654 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006655 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006656 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006657 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006658 }
6659
6660 // Fall through to send to the superclass in CDecl.
6661 } else {
6662 // "super" may be the name of a type or variable. Figure out which
6663 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006664 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006665 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006666 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6667 // "super" names an interface. Use it.
6668 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006669 if (const ObjCObjectType *Iface =
6670 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006671 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006672 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6673 // "super" names an unresolved type; we can't be more specific.
6674 } else {
6675 // Assume that "super" names some kind of value and parse that way.
6676 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006677 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006678 UnqualifiedId id;
6679 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006680 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6681 /*HasTrailingLParen=*/false,
6682 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006683 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006684 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006685 }
6686
6687 // Fall through
6688 }
6689
John McCallba7bf592010-08-24 05:47:05 +00006690 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006691 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006692 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006693 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006694 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006695 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006696}
6697
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006698/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006699/// send, determine the preferred type (if any) for that argument expression.
6700static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6701 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006702 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006703 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006704
Douglas Gregor74661272010-09-21 00:03:25 +00006705 QualType PreferredType;
6706 unsigned BestPriority = CCP_Unlikely * 2;
6707 Result *ResultsData = Results.data();
6708 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6709 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006710 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006711 isa<ObjCMethodDecl>(R.Declaration)) {
6712 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006713 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006714 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006715 QualType MyPreferredType =
6716 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006717 if (R.Priority < BestPriority || PreferredType.isNull()) {
6718 BestPriority = R.Priority;
6719 PreferredType = MyPreferredType;
6720 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6721 MyPreferredType)) {
6722 PreferredType = QualType();
6723 }
6724 }
6725 }
6726 }
6727 }
6728
6729 return PreferredType;
6730}
6731
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006732static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006733 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006734 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006735 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006736 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006737 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006738 ObjCInterfaceDecl *CDecl = nullptr;
6739
Douglas Gregor8ce33212009-11-17 17:59:40 +00006740 // If the given name refers to an interface type, retrieve the
6741 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006742 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006743 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006744 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006745 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6746 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006747 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006748
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006749 // Add all of the factory methods in this Objective-C class, its protocols,
6750 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006751 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006752
6753 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006754 // completion.
6755 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006756 if (ObjCMethodDecl *SuperMethod =
6757 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006758 Results.Ignore(SuperMethod);
6759 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006760
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006761 // If we're inside an Objective-C method definition, prefer its selector to
6762 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006763 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006764 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006765
Douglas Gregor1154e272010-09-16 16:06:31 +00006766 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006767 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006768 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6769 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006770 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006771 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006772
Douglas Gregord720daf2010-04-06 17:30:22 +00006773 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006774 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006775 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006776 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006777 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006778 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006779 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006780 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006781 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006782
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006783 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006784 }
6785 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006786
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006787 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006788 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006789 M != MEnd; ++M) {
6790 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006791 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006792 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006793 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006794
Nico Weber2e0c8f72014-12-27 03:58:08 +00006795 Result R(MethList->getMethod(),
6796 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006797 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006798 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006799 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006800 }
6801 }
6802 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006803
6804 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006805}
Douglas Gregor6285f752010-04-06 16:40:00 +00006806
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006807void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006808 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006809 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006810 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006811
Douglas Gregor63745d52011-07-21 01:05:26 +00006812 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006813
Fangrui Song050229d2018-11-24 00:14:31 +00006814 ResultBuilder Results(
6815 *this, CodeCompleter->getAllocator(),
6816 CodeCompleter->getCodeCompletionTUInfo(),
6817 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6818 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006819
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006820 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006821 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006822
6823 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006824 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006825 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006826 // code-complete the expression using the corresponding parameter type as
6827 // our preferred type, improving completion results.
6828 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006829 QualType PreferredType =
6830 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006831 if (PreferredType.isNull())
6832 CodeCompleteOrdinaryName(S, PCC_Expression);
6833 else
6834 CodeCompleteExpression(S, PreferredType);
6835 return;
6836 }
6837
Fangrui Song050229d2018-11-24 00:14:31 +00006838 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006839 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006840}
6841
Richard Trieu2bd04012011-09-09 02:00:50 +00006842void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006843 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006844 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006845 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006846 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006847
Steve Naroffeae65032009-11-07 02:08:14 +00006848 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006849
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006850 // If necessary, apply function/array conversion to the receiver.
6851 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006852 if (RecExpr) {
6853 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6854 if (Conv.isInvalid()) // conversion failed. bail.
6855 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006856 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006857 }
Fangrui Song050229d2018-11-24 00:14:31 +00006858 QualType ReceiverType = RecExpr
6859 ? RecExpr->getType()
6860 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006861 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006862 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006863
Douglas Gregordc520b02010-11-08 21:12:30 +00006864 // If we're messaging an expression with type "id" or "Class", check
6865 // whether we know something special about the receiver that allows
6866 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006867 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006868 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6869 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006870 return CodeCompleteObjCClassMessage(
6871 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6872 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006873
Fangrui Song050229d2018-11-24 00:14:31 +00006874 ReceiverType =
6875 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006876 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006877 } else if (RecExpr && getLangOpts().CPlusPlus) {
6878 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6879 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006880 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006881 ReceiverType = RecExpr->getType();
6882 }
6883 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006884
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006885 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006886 ResultBuilder Results(
6887 *this, CodeCompleter->getAllocator(),
6888 CodeCompleter->getCodeCompletionTUInfo(),
6889 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6890 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006891
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006892 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006893
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006894 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006895 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006896 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006897 if (ObjCMethodDecl *SuperMethod =
6898 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006899 Results.Ignore(SuperMethod);
6900 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006901
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006902 // If we're inside an Objective-C method definition, prefer its selector to
6903 // others.
6904 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6905 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006906
Douglas Gregor1154e272010-09-16 16:06:31 +00006907 // Keep track of the selectors we've already added.
6908 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006909
Douglas Gregora3329fa2009-11-18 00:06:18 +00006910 // Handle messages to Class. This really isn't a message to an instance
6911 // method, so we treat it the same way we would treat a message send to a
6912 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006913 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006914 ReceiverType->isObjCQualifiedClassType()) {
6915 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6916 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006917 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6918 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006919 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006920 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006921 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006922 else if (const ObjCObjectPointerType *QualID =
6923 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006924 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006925 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006926 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6927 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006928 }
6929 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006930 else if (const ObjCObjectPointerType *IFacePtr =
6931 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006932 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006933 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006934 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006935
Douglas Gregora3329fa2009-11-18 00:06:18 +00006936 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006937 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006938 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6939 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006940 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006941 // Handle messages to "id".
6942 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006943 // We're messaging "id", so provide all instance methods we know
6944 // about as code-completion results.
6945
6946 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006947 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006948 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006949 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6950 I != N; ++I) {
6951 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006952 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006953 continue;
6954
Sebastian Redl75d8a322010-08-02 23:18:59 +00006955 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006956 }
6957 }
6958
Sebastian Redl75d8a322010-08-02 23:18:59 +00006959 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6960 MEnd = MethodPool.end();
6961 M != MEnd; ++M) {
6962 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006963 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006964 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006965 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006966
Nico Weber2e0c8f72014-12-27 03:58:08 +00006967 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006968 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006969
Nico Weber2e0c8f72014-12-27 03:58:08 +00006970 Result R(MethList->getMethod(),
6971 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006972 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006973 R.AllParametersAreInformative = false;
6974 Results.MaybeAddResult(R, CurContext);
6975 }
6976 }
6977 }
Steve Naroffeae65032009-11-07 02:08:14 +00006978 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006979
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006980 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006981 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006982 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006983 // code-complete the expression using the corresponding parameter type as
6984 // our preferred type, improving completion results.
6985 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006986 QualType PreferredType =
6987 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006988 if (PreferredType.isNull())
6989 CodeCompleteOrdinaryName(S, PCC_Expression);
6990 else
6991 CodeCompleteExpression(S, PreferredType);
6992 return;
6993 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006994
Fangrui Song050229d2018-11-24 00:14:31 +00006995 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6996 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006997}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006998
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006999void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00007000 DeclGroupPtrTy IterationVar) {
7001 CodeCompleteExpressionData Data;
7002 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007003
Douglas Gregor68762e72010-08-23 21:17:50 +00007004 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00007005 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00007006 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
7007 if (*I)
7008 Data.IgnoreDecls.push_back(*I);
7009 }
7010 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007011
Douglas Gregor68762e72010-08-23 21:17:50 +00007012 CodeCompleteExpression(S, Data);
7013}
7014
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007015void Sema::CodeCompleteObjCSelector(Scope *S,
7016 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007017 // If we have an external source, load the entire class method
7018 // pool from the AST file.
7019 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00007020 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
7021 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007022 Selector Sel = ExternalSource->GetExternalSelector(I);
7023 if (Sel.isNull() || MethodPool.count(Sel))
7024 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007025
Douglas Gregor67c692c2010-08-26 15:07:07 +00007026 ReadMethodPool(Sel);
7027 }
7028 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007029
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007030 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007031 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007032 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00007033 Results.EnterNewScope();
7034 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007035 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00007036 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007037
Douglas Gregor67c692c2010-08-26 15:07:07 +00007038 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007039 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00007040 continue;
7041
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007042 CodeCompletionBuilder Builder(Results.getAllocator(),
7043 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007044 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007045 Builder.AddTypedTextChunk(
7046 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007047 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007048 continue;
7049 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007050
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007051 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00007052 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007053 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007054 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007055 Builder.AddInformativeChunk(
7056 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007057 Accumulator.clear();
7058 }
7059 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007060
Benjamin Kramer632500c2011-07-26 16:59:25 +00007061 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007062 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00007063 }
Fangrui Song050229d2018-11-24 00:14:31 +00007064 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007065 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007066 }
7067 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007068
7069 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00007070 Results.data(), Results.size());
7071}
7072
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007073/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00007074/// (translation unit) context.
7075static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007076 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00007077 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007078 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007079
Aaron Ballman629afae2014-03-07 19:56:05 +00007080 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00007081 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007082 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00007083 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00007084 Results.AddResult(
7085 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
7086 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007087 }
7088}
7089
Craig Topper883dd332015-12-24 23:58:11 +00007090void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00007091 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007092 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007093 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007094 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007095
Chandler Carruthede11632016-11-04 06:06:50 +00007096 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007097 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007098
Douglas Gregora3b23b02010-12-09 21:44:02 +00007099 // Tell the result set to ignore all of the protocols we have
7100 // already seen.
7101 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00007102 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00007103 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00007104 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007105
Douglas Gregora3b23b02010-12-09 21:44:02 +00007106 // Add all protocols.
7107 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
7108 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007109
Douglas Gregora3b23b02010-12-09 21:44:02 +00007110 Results.ExitScope();
7111 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00007112
7113 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7114 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007115}
7116
7117void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007118 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007119 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007120 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007121
Chandler Carruthede11632016-11-04 06:06:50 +00007122 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007123 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007124
Douglas Gregora3b23b02010-12-09 21:44:02 +00007125 // Add all protocols.
7126 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
7127 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +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 Gregorbaf69612009-11-18 04:19:12 +00007134}
Douglas Gregor49c22a72009-11-18 16:26:39 +00007135
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007136/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00007137/// the given (translation unit) context.
7138static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
7139 bool OnlyForwardDeclarations,
7140 bool OnlyUnimplemented,
7141 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007142 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007143
Aaron Ballman629afae2014-03-07 19:56:05 +00007144 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00007145 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007146 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00007147 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00007148 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00007149 Results.AddResult(
7150 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
7151 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007152 }
7153}
7154
Eric Liuf5ba09f2018-07-04 10:01:18 +00007155void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007156 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007157 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007158 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007159 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007160
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007161 if (CodeCompleter->includeGlobals()) {
7162 // Add all classes.
7163 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7164 false, Results);
7165 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007166
Douglas Gregor49c22a72009-11-18 16:26:39 +00007167 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007168
Eric Liuf5ba09f2018-07-04 10:01:18 +00007169 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7170 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007171}
7172
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007173void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007174 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007175 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007176 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007177 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007178 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007179
Douglas Gregor49c22a72009-11-18 16:26:39 +00007180 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00007181 NamedDecl *CurClass =
7182 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007183 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00007184 Results.Ignore(CurClass);
7185
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007186 if (CodeCompleter->includeGlobals()) {
7187 // Add all classes.
7188 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7189 false, Results);
7190 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007191
Douglas Gregor49c22a72009-11-18 16:26:39 +00007192 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007193
Eric Liuf5ba09f2018-07-04 10:01:18 +00007194 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7195 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007196}
7197
Eric Liuf5ba09f2018-07-04 10:01:18 +00007198void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007199 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007200 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007201 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007202 Results.EnterNewScope();
7203
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007204 if (CodeCompleter->includeGlobals()) {
7205 // Add all unimplemented classes.
7206 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7207 true, Results);
7208 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007209
Douglas Gregor49c22a72009-11-18 16:26:39 +00007210 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007211
Eric Liuf5ba09f2018-07-04 10:01:18 +00007212 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7213 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007214}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007215
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007216void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007217 IdentifierInfo *ClassName,
7218 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007219 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007220
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007221 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007222 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007223 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007224
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007225 // Ignore any categories we find that have already been implemented by this
7226 // interface.
7227 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00007228 NamedDecl *CurClass =
7229 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
7230 if (ObjCInterfaceDecl *Class =
7231 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007232 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007233 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007234 }
7235
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007236 // Add all of the categories we know about.
7237 Results.EnterNewScope();
7238 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007239 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00007240 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00007241 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00007242 Results.AddResult(
7243 Result(Category, Results.getBasePriority(Category), nullptr),
7244 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007245 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007246
7247 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7248 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007249}
7250
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007251void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007252 IdentifierInfo *ClassName,
7253 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007254 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007255
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007256 // Find the corresponding interface. If we couldn't find the interface, the
7257 // program itself is ill-formed. However, we'll try to be helpful still by
7258 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00007259 NamedDecl *CurClass =
7260 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007261 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
7262 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007263 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007264
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007265 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007266 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007267 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007268
7269 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007270 // declarations in this class and any of its superclasses, except for
7271 // already-implemented categories in the class itself.
7272 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7273 Results.EnterNewScope();
7274 bool IgnoreImplemented = true;
7275 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007276 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007277 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007278 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007279 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7280 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007281 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007282
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007283 Class = Class->getSuperClass();
7284 IgnoreImplemented = false;
7285 }
7286 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007287
7288 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7289 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007290}
Douglas Gregor5d649882009-11-18 22:32:06 +00007291
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007292void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007293 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007294 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007295 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007296
7297 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007298 ObjCContainerDecl *Container =
7299 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7300 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7301 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007302 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007303
7304 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007305 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007306 for (const auto *D : Container->decls())
7307 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007308 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007309
Douglas Gregor5d649882009-11-18 22:32:06 +00007310 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007311 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007312 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007313 if (ObjCImplementationDecl *ClassImpl =
7314 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007315 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007316 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007317 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007318 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007319 AddObjCProperties(CCContext,
7320 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007321 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007322 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007323 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007324
7325 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7326 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007327}
7328
Fangrui Song050229d2018-11-24 00:14:31 +00007329void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7330 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007331 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007332 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007333 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007334 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007335
7336 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007337 ObjCContainerDecl *Container =
7338 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7339 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7340 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007341 return;
7342
Douglas Gregor5d649882009-11-18 22:32:06 +00007343 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007344 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007345 if (ObjCImplementationDecl *ClassImpl =
7346 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007347 Class = ClassImpl->getClassInterface();
7348 else
Fangrui Song050229d2018-11-24 00:14:31 +00007349 Class = cast<ObjCCategoryImplDecl>(Container)
7350 ->getCategoryDecl()
7351 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007352
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007353 // Determine the type of the property we're synthesizing.
7354 QualType PropertyType = Context.getObjCIdType();
7355 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007356 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7357 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007358 PropertyType =
7359 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007360
7361 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007362 Results.setPreferredType(PropertyType);
7363 }
7364 }
7365
Douglas Gregor5d649882009-11-18 22:32:06 +00007366 // Add all of the instance variables in this class and its superclasses.
7367 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007368 bool SawSimilarlyNamedIvar = false;
7369 std::string NameWithPrefix;
7370 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007371 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007372 std::string NameWithSuffix = PropertyName->getName().str();
7373 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007374 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007375 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007376 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007377 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7378 CurContext, nullptr, false);
7379
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007380 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007381 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007382 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007383 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007384 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007385 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007386
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007387 // Reduce the priority of this result by one, to give it a slight
7388 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007389 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007390 Results.data()[Results.size() - 1].Kind ==
7391 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007392 Results.data()[Results.size() - 1].Declaration == Ivar)
7393 Results.data()[Results.size() - 1].Priority--;
7394 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007395 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007396 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007397
Douglas Gregor331faa02011-04-18 14:13:53 +00007398 if (!SawSimilarlyNamedIvar) {
7399 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007400 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007401 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007402 typedef CodeCompletionResult Result;
7403 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007404 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007405 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007406
Douglas Gregor75acd922011-09-27 23:30:47 +00007407 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007408 Builder.AddResultTypeChunk(
7409 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007410 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007411 Results.AddResult(
7412 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007413 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007414
Douglas Gregor5d649882009-11-18 22:32:06 +00007415 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007416
7417 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7418 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007419}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007420
Douglas Gregor416b5752010-08-25 01:08:01 +00007421// Mapping from selectors to the methods that implement that selector, along
7422// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007423typedef llvm::DenseMap<Selector,
7424 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7425 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007426
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007427/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007428/// (and its superclasses, protocols, etc.) that meet the given
7429/// criteria. Insert those methods into the map of known methods,
7430/// indexed by selector so they can be easily found.
7431static void FindImplementableMethods(ASTContext &Context,
7432 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007433 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007434 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007435 KnownMethodsMap &KnownMethods,
7436 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007437 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007438 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007439 if (!IFace->hasDefinition())
7440 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007441
7442 IFace = IFace->getDefinition();
7443 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007444
Fangrui Song050229d2018-11-24 00:14:31 +00007445 const ObjCList<ObjCProtocolDecl> &Protocols =
7446 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007447 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007448 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007449 I != E; ++I)
7450 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007451 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007452
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007453 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007454 for (auto *Cat : IFace->visible_categories()) {
7455 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007456 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007457 }
7458
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007459 // Visit the superclass.
7460 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007461 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007462 WantInstanceMethods, ReturnType, KnownMethods,
7463 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007464 }
7465
7466 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7467 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007468 const ObjCList<ObjCProtocolDecl> &Protocols =
7469 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007470 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007471 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007472 I != E; ++I)
7473 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007474 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007475
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007476 // If this category is the original class, jump to the interface.
7477 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007478 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007479 WantInstanceMethods, ReturnType, KnownMethods,
7480 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007481 }
7482
7483 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007484 // Make sure we have a definition; that's what we'll walk.
7485 if (!Protocol->hasDefinition())
7486 return;
7487 Protocol = Protocol->getDefinition();
7488 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007489
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007490 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007491 const ObjCList<ObjCProtocolDecl> &Protocols =
7492 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007493 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007494 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007495 I != E; ++I)
7496 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7497 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007498 }
7499
7500 // Add methods in this container. This operation occurs last because
7501 // we want the methods from this container to override any methods
7502 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007503 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007504 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007505 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007506 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007507 continue;
7508
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007509 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007510 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007511 }
7512 }
7513}
7514
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007515/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007516/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007517static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007518 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007519 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007520 CodeCompletionBuilder &Builder) {
7521 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007522 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007523 if (!Quals.empty())
7524 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007525 Builder.AddTextChunk(
7526 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007527 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7528}
7529
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007530/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007531/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007532static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007533 if (!Class)
7534 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007535
Douglas Gregor669a25a2011-02-17 00:22:45 +00007536 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7537 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007538
Douglas Gregor669a25a2011-02-17 00:22:45 +00007539 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7540}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007541
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007542/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007543/// Key-Value Observing (KVO).
7544static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7545 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007546 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007547 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007548 ResultBuilder &Results) {
7549 IdentifierInfo *PropName = Property->getIdentifier();
7550 if (!PropName || PropName->getLength() == 0)
7551 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007552
Douglas Gregor75acd922011-09-27 23:30:47 +00007553 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7554
Douglas Gregor669a25a2011-02-17 00:22:45 +00007555 // Builder that will create each code completion.
7556 typedef CodeCompletionResult Result;
7557 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007558 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007559
Douglas Gregor669a25a2011-02-17 00:22:45 +00007560 // The selector table.
7561 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007562
Douglas Gregor669a25a2011-02-17 00:22:45 +00007563 // The property name, copied into the code completion allocation region
7564 // on demand.
7565 struct KeyHolder {
7566 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007567 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007568 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007569
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007570 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007571 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007572
Douglas Gregor669a25a2011-02-17 00:22:45 +00007573 operator const char *() {
7574 if (CopiedKey)
7575 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007576
Douglas Gregor669a25a2011-02-17 00:22:45 +00007577 return CopiedKey = Allocator.CopyString(Key);
7578 }
7579 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007580
Douglas Gregor669a25a2011-02-17 00:22:45 +00007581 // The uppercased name of the property name.
7582 std::string UpperKey = PropName->getName();
7583 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007584 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007585
Fangrui Song050229d2018-11-24 00:14:31 +00007586 bool ReturnTypeMatchesProperty =
7587 ReturnType.isNull() ||
7588 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7589 Property->getType());
7590 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007591
Douglas Gregor669a25a2011-02-17 00:22:45 +00007592 // Add the normal accessor -(type)key.
7593 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007594 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007595 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7596 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007597 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7598 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007599
Douglas Gregor669a25a2011-02-17 00:22:45 +00007600 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007601 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007602 CXCursor_ObjCInstanceMethodDecl));
7603 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007604
Douglas Gregor669a25a2011-02-17 00:22:45 +00007605 // If we have an integral or boolean property (or the user has provided
7606 // an integral or boolean return type), add the accessor -(type)isKey.
7607 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007608 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007609 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007610 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7611 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007612 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007613 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007614 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7615 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007616 if (ReturnType.isNull()) {
7617 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7618 Builder.AddTextChunk("BOOL");
7619 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7620 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007621
Fangrui Song050229d2018-11-24 00:14:31 +00007622 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007623 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007624 CXCursor_ObjCInstanceMethodDecl));
7625 }
7626 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007627
Douglas Gregor669a25a2011-02-17 00:22:45 +00007628 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007629 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007630 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007631 std::string SelectorName = (Twine("set") + 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.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007634 if (ReturnType.isNull()) {
7635 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7636 Builder.AddTextChunk("void");
7637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7638 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007639
Fangrui Song050229d2018-11-24 00:14:31 +00007640 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007641 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007642 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7643 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007644 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007645 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007646 CXCursor_ObjCInstanceMethodDecl));
7647 }
7648 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007649
Douglas Gregor669a25a2011-02-17 00:22:45 +00007650 // Indexed and unordered accessors
7651 unsigned IndexedGetterPriority = CCP_CodePattern;
7652 unsigned IndexedSetterPriority = CCP_CodePattern;
7653 unsigned UnorderedGetterPriority = CCP_CodePattern;
7654 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007655 if (const auto *ObjCPointer =
7656 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007657 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7658 // If this interface type is not provably derived from a known
7659 // collection, penalize the corresponding completions.
7660 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007661 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007662 if (!InheritsFromClassNamed(IFace, "NSArray"))
7663 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7664 }
7665
7666 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007667 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007668 if (!InheritsFromClassNamed(IFace, "NSSet"))
7669 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7670 }
7671 }
7672 } else {
7673 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7674 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7675 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7676 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7677 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007678
Douglas Gregor669a25a2011-02-17 00:22:45 +00007679 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007680 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007681 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007682 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007683 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007684 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7685 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007686 if (ReturnType.isNull()) {
7687 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7688 Builder.AddTextChunk("NSUInteger");
7689 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7690 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007691
Fangrui Song050229d2018-11-24 00:14:31 +00007692 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7693 Results.AddResult(
7694 Result(Builder.TakeString(),
7695 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7696 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007697 }
7698 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007699
Douglas Gregor669a25a2011-02-17 00:22:45 +00007700 // Indexed getters
7701 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7702 if (IsInstanceMethod &&
7703 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007704 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007705 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007706 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007707 if (ReturnType.isNull()) {
7708 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7709 Builder.AddTextChunk("id");
7710 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7711 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007712
Douglas Gregor669a25a2011-02-17 00:22:45 +00007713 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7714 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7715 Builder.AddTextChunk("NSUInteger");
7716 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7717 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007718 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007719 CXCursor_ObjCInstanceMethodDecl));
7720 }
7721 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007722
Douglas Gregor669a25a2011-02-17 00:22:45 +00007723 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7724 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007725 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007726 (ReturnType->isObjCObjectPointerType() &&
7727 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007728 ReturnType->getAs<ObjCObjectPointerType>()
7729 ->getInterfaceDecl()
7730 ->getName() == "NSArray"))) {
7731 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007732 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007733 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007734 if (ReturnType.isNull()) {
7735 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7736 Builder.AddTextChunk("NSArray *");
7737 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7738 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007739
Douglas Gregor669a25a2011-02-17 00:22:45 +00007740 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7741 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7742 Builder.AddTextChunk("NSIndexSet *");
7743 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7744 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007745 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007746 CXCursor_ObjCInstanceMethodDecl));
7747 }
7748 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007749
Douglas Gregor669a25a2011-02-17 00:22:45 +00007750 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7751 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007752 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007753 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7754 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007755
David Blaikie82e95a32014-11-19 07:49:47 +00007756 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007757 if (ReturnType.isNull()) {
7758 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7759 Builder.AddTextChunk("void");
7760 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7761 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007762
Douglas Gregor669a25a2011-02-17 00:22:45 +00007763 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7764 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7765 Builder.AddPlaceholderChunk("object-type");
7766 Builder.AddTextChunk(" **");
7767 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7768 Builder.AddTextChunk("buffer");
7769 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7770 Builder.AddTypedTextChunk("range:");
7771 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7772 Builder.AddTextChunk("NSRange");
7773 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7774 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007775 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007776 CXCursor_ObjCInstanceMethodDecl));
7777 }
7778 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007779
Douglas Gregor669a25a2011-02-17 00:22:45 +00007780 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007781
Douglas Gregor669a25a2011-02-17 00:22:45 +00007782 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7783 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007784 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007785 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7786 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007787
David Blaikie82e95a32014-11-19 07:49:47 +00007788 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007789 if (ReturnType.isNull()) {
7790 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7791 Builder.AddTextChunk("void");
7792 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7793 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007794
Douglas Gregor669a25a2011-02-17 00:22:45 +00007795 Builder.AddTypedTextChunk("insertObject:");
7796 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7797 Builder.AddPlaceholderChunk("object-type");
7798 Builder.AddTextChunk(" *");
7799 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7800 Builder.AddTextChunk("object");
7801 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7802 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7803 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7804 Builder.AddPlaceholderChunk("NSUInteger");
7805 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7806 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007807 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007808 CXCursor_ObjCInstanceMethodDecl));
7809 }
7810 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007811
Douglas Gregor669a25a2011-02-17 00:22:45 +00007812 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7813 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007814 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007815 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7816 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007817
David Blaikie82e95a32014-11-19 07:49:47 +00007818 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007819 if (ReturnType.isNull()) {
7820 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7821 Builder.AddTextChunk("void");
7822 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7823 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007824
Douglas Gregor669a25a2011-02-17 00:22:45 +00007825 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7826 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7827 Builder.AddTextChunk("NSArray *");
7828 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7829 Builder.AddTextChunk("array");
7830 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7831 Builder.AddTypedTextChunk("atIndexes:");
7832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7833 Builder.AddPlaceholderChunk("NSIndexSet *");
7834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7835 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007836 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007837 CXCursor_ObjCInstanceMethodDecl));
7838 }
7839 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007840
Douglas Gregor669a25a2011-02-17 00:22:45 +00007841 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7842 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007843 std::string SelectorName =
7844 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007845 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007846 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007847 if (ReturnType.isNull()) {
7848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7849 Builder.AddTextChunk("void");
7850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7851 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007852
Douglas Gregor669a25a2011-02-17 00:22:45 +00007853 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7854 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7855 Builder.AddTextChunk("NSUInteger");
7856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7857 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007858 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007859 CXCursor_ObjCInstanceMethodDecl));
7860 }
7861 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007862
Douglas Gregor669a25a2011-02-17 00:22:45 +00007863 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7864 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007865 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007866 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007867 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007868 if (ReturnType.isNull()) {
7869 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7870 Builder.AddTextChunk("void");
7871 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7872 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007873
Douglas Gregor669a25a2011-02-17 00:22:45 +00007874 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7875 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7876 Builder.AddTextChunk("NSIndexSet *");
7877 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7878 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007879 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007880 CXCursor_ObjCInstanceMethodDecl));
7881 }
7882 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007883
Douglas Gregor669a25a2011-02-17 00:22:45 +00007884 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7885 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007886 std::string SelectorName =
7887 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7888 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7889 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007890
David Blaikie82e95a32014-11-19 07:49:47 +00007891 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007892 if (ReturnType.isNull()) {
7893 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7894 Builder.AddTextChunk("void");
7895 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7896 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007897
Douglas Gregor669a25a2011-02-17 00:22:45 +00007898 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7899 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7900 Builder.AddPlaceholderChunk("NSUInteger");
7901 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7902 Builder.AddTextChunk("index");
7903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7904 Builder.AddTypedTextChunk("withObject:");
7905 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7906 Builder.AddTextChunk("id");
7907 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7908 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007909 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007910 CXCursor_ObjCInstanceMethodDecl));
7911 }
7912 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007913
Douglas Gregor669a25a2011-02-17 00:22:45 +00007914 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7915 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007916 std::string SelectorName1 =
7917 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007918 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007919 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7920 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007921
David Blaikie82e95a32014-11-19 07:49:47 +00007922 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007923 if (ReturnType.isNull()) {
7924 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7925 Builder.AddTextChunk("void");
7926 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7927 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007928
Douglas Gregor669a25a2011-02-17 00:22:45 +00007929 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7930 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7931 Builder.AddPlaceholderChunk("NSIndexSet *");
7932 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7933 Builder.AddTextChunk("indexes");
7934 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7935 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7936 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7937 Builder.AddTextChunk("NSArray *");
7938 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7939 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007940 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007941 CXCursor_ObjCInstanceMethodDecl));
7942 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007943 }
7944
Douglas Gregor669a25a2011-02-17 00:22:45 +00007945 // Unordered getters
7946 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007947 if (IsInstanceMethod &&
7948 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007949 (ReturnType->isObjCObjectPointerType() &&
7950 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007951 ReturnType->getAs<ObjCObjectPointerType>()
7952 ->getInterfaceDecl()
7953 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007954 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007955 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007956 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7957 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007958 if (ReturnType.isNull()) {
7959 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7960 Builder.AddTextChunk("NSEnumerator *");
7961 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7962 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007963
Douglas Gregor669a25a2011-02-17 00:22:45 +00007964 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007965 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007966 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007967 }
7968 }
7969
7970 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007971 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007972 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007973 std::string SelectorName = (Twine("memberOf") + 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.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007976 if (ReturnType.isNull()) {
7977 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7978 Builder.AddPlaceholderChunk("object-type");
7979 Builder.AddTextChunk(" *");
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 + ":"));
7984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7985 if (ReturnType.isNull()) {
7986 Builder.AddPlaceholderChunk("object-type");
7987 Builder.AddTextChunk(" *");
7988 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007989 Builder.AddTextChunk(GetCompletionTypeString(
7990 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007991 }
7992 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7993 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007994 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007995 CXCursor_ObjCInstanceMethodDecl));
7996 }
7997 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007998
Douglas Gregor669a25a2011-02-17 00:22:45 +00007999 // Mutable unordered accessors
8000 // - (void)addKeyObject:(type *)object
8001 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00008002 std::string SelectorName =
8003 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008004 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008005 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008006 if (ReturnType.isNull()) {
8007 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8008 Builder.AddTextChunk("void");
8009 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8010 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008011
Douglas Gregor669a25a2011-02-17 00:22:45 +00008012 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8013 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8014 Builder.AddPlaceholderChunk("object-type");
8015 Builder.AddTextChunk(" *");
8016 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8017 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008018 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008019 CXCursor_ObjCInstanceMethodDecl));
8020 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008021 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008022
8023 // - (void)addKey:(NSSet *)objects
8024 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008025 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008026 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008027 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008028 if (ReturnType.isNull()) {
8029 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8030 Builder.AddTextChunk("void");
8031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8032 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008033
Douglas Gregor669a25a2011-02-17 00:22:45 +00008034 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8035 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8036 Builder.AddTextChunk("NSSet *");
8037 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8038 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008039 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008040 CXCursor_ObjCInstanceMethodDecl));
8041 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008042 }
8043
Douglas Gregor669a25a2011-02-17 00:22:45 +00008044 // - (void)removeKeyObject:(type *)object
8045 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00008046 std::string SelectorName =
8047 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008048 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008049 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008050 if (ReturnType.isNull()) {
8051 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8052 Builder.AddTextChunk("void");
8053 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8054 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008055
Douglas Gregor669a25a2011-02-17 00:22:45 +00008056 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8057 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8058 Builder.AddPlaceholderChunk("object-type");
8059 Builder.AddTextChunk(" *");
8060 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8061 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008062 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008063 CXCursor_ObjCInstanceMethodDecl));
8064 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008065 }
8066
Douglas Gregor669a25a2011-02-17 00:22:45 +00008067 // - (void)removeKey:(NSSet *)objects
8068 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008069 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008070 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008071 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008072 if (ReturnType.isNull()) {
8073 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8074 Builder.AddTextChunk("void");
8075 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8076 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008077
Douglas Gregor669a25a2011-02-17 00:22:45 +00008078 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8079 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8080 Builder.AddTextChunk("NSSet *");
8081 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8082 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008083 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008084 CXCursor_ObjCInstanceMethodDecl));
8085 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008086 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008087
8088 // - (void)intersectKey:(NSSet *)objects
8089 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008090 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008091 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008092 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008093 if (ReturnType.isNull()) {
8094 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8095 Builder.AddTextChunk("void");
8096 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8097 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008098
Douglas Gregor669a25a2011-02-17 00:22:45 +00008099 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8100 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8101 Builder.AddTextChunk("NSSet *");
8102 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8103 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008104 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008105 CXCursor_ObjCInstanceMethodDecl));
8106 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008107 }
8108
Douglas Gregor669a25a2011-02-17 00:22:45 +00008109 // Key-Value Observing
8110 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008111 if (!IsInstanceMethod &&
8112 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00008113 (ReturnType->isObjCObjectPointerType() &&
8114 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00008115 ReturnType->getAs<ObjCObjectPointerType>()
8116 ->getInterfaceDecl()
8117 ->getName() == "NSSet"))) {
8118 std::string SelectorName =
8119 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008120 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008121 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8122 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008123 if (ReturnType.isNull()) {
8124 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00008125 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00008126 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8127 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008128
Douglas Gregor669a25a2011-02-17 00:22:45 +00008129 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008130 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008131 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00008132 }
8133 }
8134
8135 // + (BOOL)automaticallyNotifiesObserversForKey
8136 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00008137 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00008138 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00008139 std::string SelectorName =
8140 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00008141 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008142 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8143 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00008144 if (ReturnType.isNull()) {
8145 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8146 Builder.AddTextChunk("BOOL");
8147 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8148 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008149
Douglas Gregor857bcda2011-06-02 04:02:27 +00008150 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008151 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008152 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008153 }
8154 }
8155}
8156
Alex Lorenzb8740422017-10-24 16:39:37 +00008157void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008158 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008159 // Determine the return type of the method we're declaring, if
8160 // provided.
8161 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00008162 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008163 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00008164 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
8165 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008166 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008167 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00008168 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00008169 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00008170 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008171 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
8172 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008173 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00008174 } else if (ObjCCategoryImplDecl *CatImpl =
8175 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008176 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008177 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008178 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00008179 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008180 }
8181
8182 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00008183 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00008184 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008185 }
8186
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008187 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008188 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008189 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008190 return;
8191 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008192
Douglas Gregor636a61e2010-04-07 00:21:17 +00008193 // Find all of the methods that we could declare/implement here.
8194 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00008195 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
8196 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008197
Douglas Gregor636a61e2010-04-07 00:21:17 +00008198 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00008199 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008200 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008201 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008202 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008203 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00008204 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008205 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008206 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008207 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008208 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008209 CodeCompletionBuilder Builder(Results.getAllocator(),
8210 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00008211
8212 // Add the '-'/'+' prefix if it wasn't provided yet.
8213 if (!IsInstanceMethod) {
8214 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
8215 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8216 }
8217
Douglas Gregor636a61e2010-04-07 00:21:17 +00008218 // If the result type was not already provided, add it to the
8219 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008220 if (ReturnType.isNull()) {
8221 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
8222 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00008223 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
8224 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008225 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008226
8227 Selector Sel = Method->getSelector();
8228
8229 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00008230 Builder.AddTypedTextChunk(
8231 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008232
8233 // Add parameters to the pattern.
8234 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008235 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008236 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008237 P != PEnd; (void)++P, ++I) {
8238 // Add the part of the selector name.
8239 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008240 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00008241 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008242 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8243 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00008244 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008245 } else
8246 break;
8247
8248 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00008249 QualType ParamType;
8250 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
8251 ParamType = (*P)->getType();
8252 else
8253 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00008254 ParamType = ParamType.substObjCTypeArgs(
8255 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008256 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00008257 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
8258 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008259
Douglas Gregor636a61e2010-04-07 00:21:17 +00008260 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00008261 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008262 }
8263
8264 if (Method->isVariadic()) {
8265 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008266 Builder.AddChunk(CodeCompletionString::CK_Comma);
8267 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008268 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008269
Douglas Gregord37c59d2010-05-28 00:57:46 +00008270 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008271 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008272 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8273 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8274 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008275 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008276 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008277 Builder.AddTextChunk("return");
8278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8279 Builder.AddPlaceholderChunk("expression");
8280 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008281 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008282 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008283
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008284 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8285 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008286 }
8287
Douglas Gregor416b5752010-08-25 01:08:01 +00008288 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008289 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008290 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008291 setInBaseClass(R);
8292 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008293 }
8294
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008295 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008296 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008297 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008298 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008299 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008300
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008301 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008302 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008303 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008304 M != MEnd; ++M)
8305 KnownSelectors.insert(M->first);
8306
Douglas Gregor669a25a2011-02-17 00:22:45 +00008307 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8308 if (!IFace)
8309 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8310 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008311
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008312 if (IFace)
8313 for (auto *Cat : IFace->visible_categories())
8314 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008315
8316 if (IsInstanceMethod) {
8317 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8318 for (auto *P : Containers[I]->instance_properties())
8319 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8320 KnownSelectors, Results);
8321 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008322 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008323
Douglas Gregor636a61e2010-04-07 00:21:17 +00008324 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008325
8326 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8327 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008328}
Douglas Gregor95887f92010-07-08 23:20:03 +00008329
Fangrui Song050229d2018-11-24 00:14:31 +00008330void Sema::CodeCompleteObjCMethodDeclSelector(
8331 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8332 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008333 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008334 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008335 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008336 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8337 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008338 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008339 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008340 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008341
8342 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008343 }
8344 }
8345
8346 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008347 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008348 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008349 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008350 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008351
Douglas Gregor95887f92010-07-08 23:20:03 +00008352 if (ReturnTy)
8353 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008354
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008355 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008356 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8357 MEnd = MethodPool.end();
8358 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008359 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8360 : &M->second.second;
8361 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008362 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008363 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008364
Douglas Gregor45879692010-07-08 23:37:41 +00008365 if (AtParameterName) {
8366 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008367 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008368 if (NumSelIdents &&
8369 NumSelIdents <= MethList->getMethod()->param_size()) {
8370 ParmVarDecl *Param =
8371 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008372 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008373 CodeCompletionBuilder Builder(Results.getAllocator(),
8374 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008375 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008376 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008377 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008378 }
8379 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008380
Douglas Gregor45879692010-07-08 23:37:41 +00008381 continue;
8382 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008383
Nico Weber2e0c8f72014-12-27 03:58:08 +00008384 Result R(MethList->getMethod(),
8385 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008386 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008387 R.AllParametersAreInformative = false;
8388 R.DeclaringEntity = true;
8389 Results.MaybeAddResult(R, CurContext);
8390 }
8391 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008392
Douglas Gregor95887f92010-07-08 23:20:03 +00008393 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008394
8395 if (!AtParameterName && !SelIdents.empty() &&
8396 SelIdents.front()->getName().startswith("init")) {
8397 for (const auto &M : PP.macros()) {
8398 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8399 continue;
8400 Results.EnterNewScope();
8401 CodeCompletionBuilder Builder(Results.getAllocator(),
8402 Results.getCodeCompletionTUInfo());
8403 Builder.AddTypedTextChunk(
8404 Builder.getAllocator().CopyString(M.first->getName()));
8405 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8406 CXCursor_MacroDefinition));
8407 Results.ExitScope();
8408 }
8409 }
8410
Eric Liuf5ba09f2018-07-04 10:01:18 +00008411 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8412 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008413}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008414
Douglas Gregorec00a262010-08-24 22:20:20 +00008415void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008416 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008417 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008418 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008419 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008420
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008421 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008422 CodeCompletionBuilder Builder(Results.getAllocator(),
8423 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008424 Builder.AddTypedTextChunk("if");
8425 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8426 Builder.AddPlaceholderChunk("condition");
8427 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008428
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008429 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008430 Builder.AddTypedTextChunk("ifdef");
8431 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8432 Builder.AddPlaceholderChunk("macro");
8433 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008434
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008435 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008436 Builder.AddTypedTextChunk("ifndef");
8437 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8438 Builder.AddPlaceholderChunk("macro");
8439 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008440
8441 if (InConditional) {
8442 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008443 Builder.AddTypedTextChunk("elif");
8444 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8445 Builder.AddPlaceholderChunk("condition");
8446 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008447
8448 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008449 Builder.AddTypedTextChunk("else");
8450 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008451
8452 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008453 Builder.AddTypedTextChunk("endif");
8454 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008455 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008456
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008457 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008458 Builder.AddTypedTextChunk("include");
8459 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8460 Builder.AddTextChunk("\"");
8461 Builder.AddPlaceholderChunk("header");
8462 Builder.AddTextChunk("\"");
8463 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008464
8465 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008466 Builder.AddTypedTextChunk("include");
8467 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8468 Builder.AddTextChunk("<");
8469 Builder.AddPlaceholderChunk("header");
8470 Builder.AddTextChunk(">");
8471 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008472
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008473 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008474 Builder.AddTypedTextChunk("define");
8475 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8476 Builder.AddPlaceholderChunk("macro");
8477 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008478
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008479 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008480 Builder.AddTypedTextChunk("define");
8481 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8482 Builder.AddPlaceholderChunk("macro");
8483 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8484 Builder.AddPlaceholderChunk("args");
8485 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8486 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008487
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008488 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008489 Builder.AddTypedTextChunk("undef");
8490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8491 Builder.AddPlaceholderChunk("macro");
8492 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008493
8494 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008495 Builder.AddTypedTextChunk("line");
8496 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8497 Builder.AddPlaceholderChunk("number");
8498 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008499
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008500 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008501 Builder.AddTypedTextChunk("line");
8502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8503 Builder.AddPlaceholderChunk("number");
8504 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8505 Builder.AddTextChunk("\"");
8506 Builder.AddPlaceholderChunk("filename");
8507 Builder.AddTextChunk("\"");
8508 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008509
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008510 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008511 Builder.AddTypedTextChunk("error");
8512 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8513 Builder.AddPlaceholderChunk("message");
8514 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008515
8516 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008517 Builder.AddTypedTextChunk("pragma");
8518 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8519 Builder.AddPlaceholderChunk("arguments");
8520 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008521
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008522 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008523 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008524 Builder.AddTypedTextChunk("import");
8525 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8526 Builder.AddTextChunk("\"");
8527 Builder.AddPlaceholderChunk("header");
8528 Builder.AddTextChunk("\"");
8529 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008530
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008531 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008532 Builder.AddTypedTextChunk("import");
8533 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8534 Builder.AddTextChunk("<");
8535 Builder.AddPlaceholderChunk("header");
8536 Builder.AddTextChunk(">");
8537 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008538 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008539
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008540 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008541 Builder.AddTypedTextChunk("include_next");
8542 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8543 Builder.AddTextChunk("\"");
8544 Builder.AddPlaceholderChunk("header");
8545 Builder.AddTextChunk("\"");
8546 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008547
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008548 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008549 Builder.AddTypedTextChunk("include_next");
8550 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8551 Builder.AddTextChunk("<");
8552 Builder.AddPlaceholderChunk("header");
8553 Builder.AddTextChunk(">");
8554 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008555
8556 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008557 Builder.AddTypedTextChunk("warning");
8558 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8559 Builder.AddPlaceholderChunk("message");
8560 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008561
8562 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8563 // completions for them. And __include_macros is a Clang-internal extension
8564 // that we don't want to encourage anyone to use.
8565
8566 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8567 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008568
8569 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008570 Results.data(), Results.size());
8571}
8572
8573void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008574 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8575 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008576}
8577
Douglas Gregorec00a262010-08-24 22:20:20 +00008578void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008579 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008580 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008581 IsDefinition ? CodeCompletionContext::CCC_MacroName
8582 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008583 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008584 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008585 CodeCompletionBuilder Builder(Results.getAllocator(),
8586 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008587 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008588 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008589 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008590 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008591 Builder.AddTypedTextChunk(
8592 Builder.getAllocator().CopyString(M->first->getName()));
8593 Results.AddResult(CodeCompletionResult(
8594 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008595 }
8596 Results.ExitScope();
8597 } else if (IsDefinition) {
8598 // FIXME: Can we detect when the user just wrote an include guard above?
8599 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008600
Douglas Gregor0ac41382010-09-23 23:01:17 +00008601 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008602 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008603}
8604
Douglas Gregorec00a262010-08-24 22:20:20 +00008605void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008606 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008607 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008608 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008609
Douglas Gregorec00a262010-08-24 22:20:20 +00008610 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008611 AddMacroResults(PP, Results,
Sam McCall36082e32019-07-18 07:17:49 +00008612 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008613
Fangrui Song050229d2018-11-24 00:14:31 +00008614 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008615 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008616 CodeCompletionBuilder Builder(Results.getAllocator(),
8617 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008618 Builder.AddTypedTextChunk("defined");
8619 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8620 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8621 Builder.AddPlaceholderChunk("macro");
8622 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8623 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008624 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008625
8626 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8627 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008628}
8629
8630void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8631 IdentifierInfo *Macro,
8632 MacroInfo *MacroInfo,
8633 unsigned Argument) {
8634 // FIXME: In the future, we could provide "overload" results, much like we
8635 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008636
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008637 // Now just ignore this. There will be another code-completion callback
8638 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008639}
8640
Sam McCall3d8051a2018-09-18 08:40:41 +00008641// This handles completion inside an #include filename, e.g. #include <foo/ba
8642// We look for the directory "foo" under each directory on the include path,
8643// list its files, and reassemble the appropriate #include.
8644void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8645 // RelDir should use /, but unescaped \ is possible on windows!
8646 // Our completions will normalize to / for simplicity, this case is rare.
8647 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8648 // We need the native slashes for the actual file system interactions.
8649 SmallString<128> NativeRelDir = StringRef(RelDir);
8650 llvm::sys::path::native(NativeRelDir);
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008651 llvm::vfs::FileSystem &FS =
8652 getSourceManager().getFileManager().getVirtualFileSystem();
Sam McCall3d8051a2018-09-18 08:40:41 +00008653
8654 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8655 CodeCompleter->getCodeCompletionTUInfo(),
8656 CodeCompletionContext::CCC_IncludedFile);
8657 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8658
8659 // Helper: adds one file or directory completion result.
8660 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8661 SmallString<64> TypedChunk = Filename;
8662 // Directory completion is up to the slash, e.g. <sys/
8663 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8664 auto R = SeenResults.insert(TypedChunk);
8665 if (R.second) { // New completion
8666 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8667 *R.first = InternedTyped; // Avoid dangling StringRef.
8668 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8669 CodeCompleter->getCodeCompletionTUInfo());
8670 Builder.AddTypedTextChunk(InternedTyped);
8671 // The result is a "Pattern", which is pretty opaque.
8672 // We may want to include the real filename to allow smart ranking.
8673 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8674 }
8675 };
8676
8677 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008678 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8679 bool IsSystem,
8680 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008681 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008682 if (!NativeRelDir.empty()) {
8683 if (LookupType == DirectoryLookup::LT_Framework) {
8684 // For a framework dir, #include <Foo/Bar/> actually maps to
8685 // a path of Foo.framework/Headers/Bar/.
8686 auto Begin = llvm::sys::path::begin(NativeRelDir);
8687 auto End = llvm::sys::path::end(NativeRelDir);
8688
8689 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8690 llvm::sys::path::append(Dir, ++Begin, End);
8691 } else {
8692 llvm::sys::path::append(Dir, NativeRelDir);
8693 }
8694 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008695
8696 std::error_code EC;
8697 unsigned Count = 0;
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008698 for (auto It = FS.dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008699 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008700 if (++Count == 2500) // If we happen to hit a huge directory,
8701 break; // bail out early so we're not too slow.
8702 StringRef Filename = llvm::sys::path::filename(It->path());
8703 switch (It->type()) {
8704 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008705 // All entries in a framework directory must have a ".framework" suffix,
8706 // but the suffix does not appear in the source code's include/import.
8707 if (LookupType == DirectoryLookup::LT_Framework &&
8708 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8709 break;
8710
Sam McCall3d8051a2018-09-18 08:40:41 +00008711 AddCompletion(Filename, /*IsDirectory=*/true);
8712 break;
8713 case llvm::sys::fs::file_type::regular_file:
8714 // Only files that really look like headers. (Except in system dirs).
8715 if (!IsSystem) {
8716 // Header extensions from Types.def, which we can't depend on here.
8717 if (!(Filename.endswith_lower(".h") ||
8718 Filename.endswith_lower(".hh") ||
8719 Filename.endswith_lower(".hpp") ||
8720 Filename.endswith_lower(".inc")))
8721 break;
8722 }
8723 AddCompletion(Filename, /*IsDirectory=*/false);
8724 break;
8725 default:
8726 break;
8727 }
8728 }
8729 };
8730
8731 // Helper: adds results relative to IncludeDir, if possible.
8732 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8733 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008734 switch (IncludeDir.getLookupType()) {
8735 case DirectoryLookup::LT_HeaderMap:
8736 // header maps are not (currently) enumerable.
8737 break;
8738 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008739 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8740 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008741 break;
8742 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008743 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8744 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008745 break;
8746 }
8747 };
8748
8749 // Finally with all our helpers, we can scan the include path.
8750 // Do this in standard order so deduplication keeps the right file.
8751 // (In case we decide to add more details to the results later).
8752 const auto &S = PP.getHeaderSearchInfo();
8753 using llvm::make_range;
8754 if (!Angled) {
8755 // The current directory is on the include path for "quoted" includes.
8756 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8757 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008758 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8759 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008760 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8761 AddFilesFromDirLookup(D, false);
8762 }
8763 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008764 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008765 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8766 AddFilesFromDirLookup(D, true);
8767
8768 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8769 Results.data(), Results.size());
8770}
8771
Douglas Gregor11583702010-08-25 17:04:25 +00008772void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008773 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008774 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8775 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008776}
8777
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008778void Sema::CodeCompleteAvailabilityPlatformName() {
8779 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8780 CodeCompleter->getCodeCompletionTUInfo(),
8781 CodeCompletionContext::CCC_Other);
8782 Results.EnterNewScope();
8783 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8784 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8785 Results.AddResult(CodeCompletionResult(Platform));
8786 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8787 Twine(Platform) + "ApplicationExtension")));
8788 }
8789 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008790 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8791 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008792}
8793
Fangrui Song050229d2018-11-24 00:14:31 +00008794void Sema::GatherGlobalCodeCompletions(
8795 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8796 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008797 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8798 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008799 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008800 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008801 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008802 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8803 Consumer,
8804 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008805 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008806
Douglas Gregorb14904c2010-08-13 22:48:40 +00008807 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008808 AddMacroResults(PP, Builder,
Sam McCall36082e32019-07-18 07:17:49 +00008809 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008810
Douglas Gregorb14904c2010-08-13 22:48:40 +00008811 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008812 Results.insert(Results.end(), Builder.data(),
8813 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008814}