blob: e4bbee86e3502dc40887ba13eeddbb657dc5eeb3 [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) {
1188 if (Candidate.isVariadic() != Incumbent.isVariadic() ||
1189 Candidate.getNumParams() != Incumbent.getNumParams() ||
1190 Candidate.getMinRequiredArguments() !=
1191 Incumbent.getMinRequiredArguments())
1192 return OverloadCompare::BothViable;
1193 for (unsigned I = 0, E = Candidate.getNumParams(); I != E; ++I)
1194 if (Candidate.parameters()[I]->getType().getCanonicalType() !=
1195 Incumbent.parameters()[I]->getType().getCanonicalType())
1196 return OverloadCompare::BothViable;
1197 if (!llvm::empty(Candidate.specific_attrs<EnableIfAttr>()) ||
1198 !llvm::empty(Incumbent.specific_attrs<EnableIfAttr>()))
1199 return OverloadCompare::BothViable;
1200 // At this point, we know calls can't pick one or the other based on
1201 // arguments, so one of the two must win. (Or both fail, handled elsewhere).
1202 RefQualifierKind CandidateRef = Candidate.getRefQualifier();
1203 RefQualifierKind IncumbentRef = Incumbent.getRefQualifier();
1204 if (CandidateRef != IncumbentRef) {
1205 // If the object kind is LValue/RValue, there's one acceptable ref-qualifier
1206 // and it can't be mixed with ref-unqualified overloads (in valid code).
1207
1208 // For xvalue objects, we prefer the rvalue overload even if we have to
1209 // add qualifiers (which is rare, because const&& is rare).
1210 if (ObjectKind == clang::VK_XValue)
1211 return CandidateRef == RQ_RValue ? OverloadCompare::Dominates
1212 : OverloadCompare::Dominated;
1213 }
1214 // Now the ref qualifiers are the same (or we're in some invalid state).
1215 // So make some decision based on the qualifiers.
1216 Qualifiers CandidateQual = Candidate.getMethodQualifiers();
1217 Qualifiers IncumbentQual = Incumbent.getMethodQualifiers();
1218 bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual);
1219 bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual);
1220 if (CandidateSuperset == IncumbentSuperset)
1221 return OverloadCompare::BothViable;
1222 return IncumbentSuperset ? OverloadCompare::Dominates
1223 : OverloadCompare::Dominated;
1224}
1225
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001226void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +00001227 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001228 if (R.Kind != Result::RK_Declaration) {
1229 // For non-declaration results, just add the result.
1230 Results.push_back(R);
1231 return;
1232 }
1233
Douglas Gregorc580c522010-01-14 01:09:38 +00001234 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +00001235 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001236 CodeCompletionResult Result(Using->getTargetDecl(),
1237 getBasePriority(Using->getTargetDecl()),
1238 R.Qualifier);
1239 Result.ShadowDecl = Using;
1240 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +00001241 return;
1242 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001243
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001244 bool AsNestedNameSpecifier = false;
1245 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +00001246 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001247
Douglas Gregor0212fd72010-09-21 16:06:22 +00001248 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +00001249 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +00001250 return;
1251
Douglas Gregorc580c522010-01-14 01:09:38 +00001252 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
1253 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +00001254
Douglas Gregorc580c522010-01-14 01:09:38 +00001255 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +00001256 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +00001257 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001258
Douglas Gregorc580c522010-01-14 01:09:38 +00001259 // If the filter is for nested-name-specifiers, then this result starts a
1260 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +00001261 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +00001262 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001263 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001264 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1265 InBaseClass &&
1266 isa<CXXRecordDecl>(
1267 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001268 R.QualifierIsInformative = true;
1269
Douglas Gregorc580c522010-01-14 01:09:38 +00001270 // If this result is supposed to have an informative qualifier, add one.
1271 if (R.QualifierIsInformative && !R.Qualifier &&
1272 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001273 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001274 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1275 R.Qualifier =
1276 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1277 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1278 R.Qualifier = NestedNameSpecifier::Create(
1279 SemaRef.Context, nullptr, false,
1280 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001281 else
1282 R.QualifierIsInformative = false;
1283 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001284
Douglas Gregora2db7932010-05-26 22:00:08 +00001285 // Adjust the priority if this result comes from a base class.
1286 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001287 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001288
Douglas Gregor50832e02010-09-20 22:39:41 +00001289 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001290
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001291 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001292 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001293 if (Method->isInstance()) {
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00001294 Qualifiers MethodQuals = Method->getMethodQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001295 if (ObjectTypeQualifiers == MethodQuals)
1296 R.Priority += CCD_ObjectQualifierMatch;
1297 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001298 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001299 // qualifiers.
1300 return;
1301 }
Sam McCall3dea5272019-06-10 15:17:52 +00001302 // Detect cases where a ref-qualified method cannot be invoked.
1303 switch (Method->getRefQualifier()) {
1304 case RQ_LValue:
1305 if (ObjectKind != VK_LValue && !MethodQuals.hasConst())
1306 return;
1307 break;
1308 case RQ_RValue:
1309 if (ObjectKind == VK_LValue)
1310 return;
1311 break;
1312 case RQ_None:
1313 break;
1314 }
1315
1316 /// Check whether this dominates another overloaded method, which should
1317 /// be suppressed (or vice versa).
1318 /// Motivating case is const_iterator begin() const vs iterator begin().
1319 auto &OverloadSet = OverloadMap[std::make_pair(
1320 CurContext, Method->getDeclName().getAsOpaqueInteger())];
1321 for (const DeclIndexPair& Entry : OverloadSet) {
1322 Result &Incumbent = Results[Entry.second];
1323 switch (compareOverloads(*Method,
1324 *cast<CXXMethodDecl>(Incumbent.Declaration),
1325 ObjectTypeQualifiers, ObjectKind)) {
1326 case OverloadCompare::Dominates:
1327 // Replace the dominated overload with this one.
1328 // FIXME: if the overload dominates multiple incumbents then we
1329 // should remove all. But two overloads is by far the common case.
1330 Incumbent = std::move(R);
1331 return;
1332 case OverloadCompare::Dominated:
1333 // This overload can't be called, drop it.
1334 return;
1335 case OverloadCompare::BothViable:
1336 break;
1337 }
1338 }
1339 OverloadSet.Add(Method, Results.size());
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001340 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001341
Douglas Gregorc580c522010-01-14 01:09:38 +00001342 // Insert this result into the set of results.
1343 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001344
Douglas Gregor0212fd72010-09-21 16:06:22 +00001345 if (!AsNestedNameSpecifier)
1346 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001347}
1348
Douglas Gregor78a21012010-01-14 16:01:26 +00001349void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001350 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001351 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001352 Results.push_back(R);
1353}
1354
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001355/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001356void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001357
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001358/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001359void ResultBuilder::ExitScope() {
1360 ShadowMaps.pop_back();
1361}
1362
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001363/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001364/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001365bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001366 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001367
Richard Smith541b38b2013-09-20 01:15:31 +00001368 // If name lookup finds a local extern declaration, then we are in a
1369 // context where it behaves like an ordinary name.
1370 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001371 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001372 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001373 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001374 if (isa<ObjCIvarDecl>(ND))
1375 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001376 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001377
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001378 return ND->getIdentifierNamespace() & IDNS;
1379}
1380
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001381/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001382/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001383bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001384 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001385 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001386 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001387 // Objective-C interfaces names are not filtered by this method because they
1388 // can be used in a class property expression. We can still filter out
1389 // @class declarations though.
1390 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1391 if (!ID->getDefinition())
1392 return false;
1393 }
1394
Richard Smith541b38b2013-09-20 01:15:31 +00001395 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001396 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001397 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001398 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001399 if (isa<ObjCIvarDecl>(ND))
1400 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001401 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001402
Douglas Gregor70febae2010-05-28 00:49:12 +00001403 return ND->getIdentifierNamespace() & IDNS;
1404}
1405
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001406bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001407 if (!IsOrdinaryNonTypeName(ND))
1408 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001409
Fangrui Song050229d2018-11-24 00:14:31 +00001410 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001411 if (VD->getType()->isIntegralOrEnumerationType())
1412 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001413
Douglas Gregor85b50632010-07-28 21:50:18 +00001414 return false;
1415}
1416
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001417/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001418/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001419bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001420 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001421
Richard Smith541b38b2013-09-20 01:15:31 +00001422 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001423 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001424 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001425
Fangrui Song050229d2018-11-24 00:14:31 +00001426 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1427 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001428}
1429
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001430/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001431/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001432bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001433 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001434 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001435 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001436
Douglas Gregor3545ff42009-09-21 16:56:56 +00001437 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1438}
1439
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001440/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001441bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001442 return isa<EnumDecl>(ND);
1443}
1444
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001445/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001446bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001447 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001448 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001449 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001450
1451 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001452 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1453 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1454 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001455
Douglas Gregor3545ff42009-09-21 16:56:56 +00001456 return false;
1457}
1458
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001459/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001460bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001461 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001462 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001463 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001464
Fangrui Song050229d2018-11-24 00:14:31 +00001465 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001466 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001467
Douglas Gregor3545ff42009-09-21 16:56:56 +00001468 return false;
1469}
1470
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001471/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001472bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001473 return isa<NamespaceDecl>(ND);
1474}
1475
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001476/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001477/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001478bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001479 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001480}
1481
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001482/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001483bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001484 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001485 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001486}
1487
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001488/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001489/// "." or "->". Only value declarations, nested name specifiers, and
1490/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001491bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001492 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001493 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001494 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001495}
1496
Douglas Gregora817a192010-05-27 23:06:34 +00001497static bool isObjCReceiverType(ASTContext &C, QualType T) {
1498 T = C.getCanonicalType(T);
1499 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001500 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001501 case Type::ObjCInterface:
1502 case Type::ObjCObjectPointer:
1503 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001504
Douglas Gregora817a192010-05-27 23:06:34 +00001505 case Type::Builtin:
1506 switch (cast<BuiltinType>(T)->getKind()) {
1507 case BuiltinType::ObjCId:
1508 case BuiltinType::ObjCClass:
1509 case BuiltinType::ObjCSel:
1510 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001511
Douglas Gregora817a192010-05-27 23:06:34 +00001512 default:
1513 break;
1514 }
1515 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001516
Douglas Gregora817a192010-05-27 23:06:34 +00001517 default:
1518 break;
1519 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001520
David Blaikiebbafb8a2012-03-11 07:00:24 +00001521 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001522 return false;
1523
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001524 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001525 // particular class type has any conversions to Objective-C types. For now,
1526 // just accept all class types.
1527 return T->isDependentType() || T->isRecordType();
1528}
1529
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001530bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001531 QualType T = getDeclUsageType(SemaRef.Context, ND);
1532 if (T.isNull())
1533 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001534
Douglas Gregora817a192010-05-27 23:06:34 +00001535 T = SemaRef.Context.getBaseElementType(T);
1536 return isObjCReceiverType(SemaRef.Context, T);
1537}
1538
Fangrui Song050229d2018-11-24 00:14:31 +00001539bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1540 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001541 if (IsObjCMessageReceiver(ND))
1542 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001543
Fangrui Song050229d2018-11-24 00:14:31 +00001544 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001545 if (!Var)
1546 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001547
Douglas Gregord8c61782012-02-15 15:34:24 +00001548 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1549}
1550
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001551bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001552 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1553 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001554 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001555
Douglas Gregor68762e72010-08-23 21:17:50 +00001556 QualType T = getDeclUsageType(SemaRef.Context, ND);
1557 if (T.isNull())
1558 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001559
Douglas Gregor68762e72010-08-23 21:17:50 +00001560 T = SemaRef.Context.getBaseElementType(T);
1561 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001562 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001563 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001564}
Douglas Gregora817a192010-05-27 23:06:34 +00001565
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001566bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001567 return false;
1568}
1569
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001570/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001571/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001572bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001573 return isa<ObjCIvarDecl>(ND);
1574}
1575
Douglas Gregorc580c522010-01-14 01:09:38 +00001576namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001577
Fangrui Song050229d2018-11-24 00:14:31 +00001578/// Visible declaration consumer that adds a code-completion result
1579/// for each visible declaration.
1580class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1581 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001582 DeclContext *InitialLookupCtx;
1583 // NamingClass and BaseType are used for access-checking. See
1584 // Sema::IsSimplyAccessible for details.
1585 CXXRecordDecl *NamingClass;
1586 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001587 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001588
Fangrui Song050229d2018-11-24 00:14:31 +00001589public:
1590 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001591 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1592 QualType BaseType = QualType(),
1593 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1594 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1595 FixIts(std::move(FixIts)) {
1596 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1597 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1598 if (BaseType.isNull()) {
1599 auto ThisType = Results.getSema().getCurrentThisType();
1600 if (!ThisType.isNull()) {
1601 assert(ThisType->isPointerType());
1602 BaseType = ThisType->getPointeeType();
1603 if (!NamingClass)
1604 NamingClass = BaseType->getAsCXXRecordDecl();
1605 }
1606 }
1607 this->BaseType = BaseType;
1608 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001609
Fangrui Song050229d2018-11-24 00:14:31 +00001610 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1611 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001612 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001613 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001614 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001615 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001616
Fangrui Song050229d2018-11-24 00:14:31 +00001617 void EnteredContext(DeclContext *Ctx) override {
1618 Results.addVisitedContext(Ctx);
1619 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001620
1621private:
1622 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1623 // Naming class to use for access check. In most cases it was provided
1624 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1625 // for unqualified lookup we fallback to the \p Ctx in which we found the
1626 // member.
1627 auto *NamingClass = this->NamingClass;
1628 QualType BaseType = this->BaseType;
1629 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1630 if (!NamingClass)
1631 NamingClass = Cls;
1632 // When we emulate implicit 'this->' in an unqualified lookup, we might
1633 // end up with an invalid naming class. In that case, we avoid emulating
1634 // 'this->' qualifier to satisfy preconditions of the access checking.
1635 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1636 !NamingClass->isDerivedFrom(Cls)) {
1637 NamingClass = Cls;
1638 BaseType = QualType();
1639 }
1640 } else {
1641 // The decl was found outside the C++ class, so only ObjC access checks
1642 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1643 // out.
1644 NamingClass = nullptr;
1645 BaseType = QualType();
1646 }
1647 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1648 }
Fangrui Song050229d2018-11-24 00:14:31 +00001649};
1650} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001651
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001652/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001653static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001654 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001655 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001656 Results.AddResult(Result("short", CCP_Type));
1657 Results.AddResult(Result("long", CCP_Type));
1658 Results.AddResult(Result("signed", CCP_Type));
1659 Results.AddResult(Result("unsigned", CCP_Type));
1660 Results.AddResult(Result("void", CCP_Type));
1661 Results.AddResult(Result("char", CCP_Type));
1662 Results.AddResult(Result("int", CCP_Type));
1663 Results.AddResult(Result("float", CCP_Type));
1664 Results.AddResult(Result("double", CCP_Type));
1665 Results.AddResult(Result("enum", CCP_Type));
1666 Results.AddResult(Result("struct", CCP_Type));
1667 Results.AddResult(Result("union", CCP_Type));
1668 Results.AddResult(Result("const", CCP_Type));
1669 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001670
Douglas Gregor3545ff42009-09-21 16:56:56 +00001671 if (LangOpts.C99) {
1672 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001673 Results.AddResult(Result("_Complex", CCP_Type));
1674 Results.AddResult(Result("_Imaginary", CCP_Type));
1675 Results.AddResult(Result("_Bool", CCP_Type));
1676 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001677 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001678
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001679 CodeCompletionBuilder Builder(Results.getAllocator(),
1680 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001681 if (LangOpts.CPlusPlus) {
1682 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001683 Results.AddResult(
1684 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001685 Results.AddResult(Result("class", CCP_Type));
1686 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001687
Douglas Gregorf4c33342010-05-28 00:22:41 +00001688 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001689 Builder.AddTypedTextChunk("typename");
1690 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1691 Builder.AddPlaceholderChunk("qualifier");
1692 Builder.AddTextChunk("::");
1693 Builder.AddPlaceholderChunk("name");
1694 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001695
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001696 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001697 Results.AddResult(Result("auto", CCP_Type));
1698 Results.AddResult(Result("char16_t", CCP_Type));
1699 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001700
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001701 Builder.AddTypedTextChunk("decltype");
1702 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1703 Builder.AddPlaceholderChunk("expression");
1704 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1705 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001706 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001707 } else
1708 Results.AddResult(Result("__auto_type", CCP_Type));
1709
Richard Smith7b301e22018-05-24 21:51:52 +00001710 // GNU keywords
1711 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001712 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001713 // Results.AddResult(Result("_Decimal32"));
1714 // Results.AddResult(Result("_Decimal64"));
1715 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001716
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001717 Builder.AddTypedTextChunk("typeof");
1718 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1719 Builder.AddPlaceholderChunk("expression");
1720 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001721
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("typeof");
1723 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1724 Builder.AddPlaceholderChunk("type");
1725 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1726 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001727 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001728
1729 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001730 Results.AddResult(Result("_Nonnull", CCP_Type));
1731 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1732 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001733}
1734
John McCallfaf5fb42010-08-26 23:41:50 +00001735static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001736 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001737 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001738 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001739 // Note: we don't suggest either "auto" or "register", because both
1740 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1741 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001742 Results.AddResult(Result("extern"));
1743 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001744
1745 if (LangOpts.CPlusPlus11) {
1746 CodeCompletionAllocator &Allocator = Results.getAllocator();
1747 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1748
1749 // alignas
1750 Builder.AddTypedTextChunk("alignas");
1751 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1752 Builder.AddPlaceholderChunk("expression");
1753 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1754 Results.AddResult(Result(Builder.TakeString()));
1755
1756 Results.AddResult(Result("constexpr"));
1757 Results.AddResult(Result("thread_local"));
1758 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001759}
1760
John McCallfaf5fb42010-08-26 23:41:50 +00001761static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001762 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001763 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001764 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001765 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001766 case Sema::PCC_Class:
1767 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001768 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001769 Results.AddResult(Result("explicit"));
1770 Results.AddResult(Result("friend"));
1771 Results.AddResult(Result("mutable"));
1772 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001773 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001774 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001775
John McCallfaf5fb42010-08-26 23:41:50 +00001776 case Sema::PCC_ObjCInterface:
1777 case Sema::PCC_ObjCImplementation:
1778 case Sema::PCC_Namespace:
1779 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001780 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001781 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001782 break;
1783
John McCallfaf5fb42010-08-26 23:41:50 +00001784 case Sema::PCC_ObjCInstanceVariableList:
1785 case Sema::PCC_Expression:
1786 case Sema::PCC_Statement:
1787 case Sema::PCC_ForInit:
1788 case Sema::PCC_Condition:
1789 case Sema::PCC_RecoveryInFunction:
1790 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001791 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001792 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001793 break;
1794 }
1795}
1796
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001797static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1798static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1799static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001800 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001801static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001802 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001803static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001804 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001805static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001806
Douglas Gregorf4c33342010-05-28 00:22:41 +00001807static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001808 CodeCompletionBuilder Builder(Results.getAllocator(),
1809 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001810 Builder.AddTypedTextChunk("typedef");
1811 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1812 Builder.AddPlaceholderChunk("type");
1813 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1814 Builder.AddPlaceholderChunk("name");
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001815 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001816 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001817}
1818
John McCallfaf5fb42010-08-26 23:41:50 +00001819static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001820 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001821 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001822 case Sema::PCC_Namespace:
1823 case Sema::PCC_Class:
1824 case Sema::PCC_ObjCInstanceVariableList:
1825 case Sema::PCC_Template:
1826 case Sema::PCC_MemberTemplate:
1827 case Sema::PCC_Statement:
1828 case Sema::PCC_RecoveryInFunction:
1829 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001830 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001831 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001832 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001833
John McCallfaf5fb42010-08-26 23:41:50 +00001834 case Sema::PCC_Expression:
1835 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001836 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001837
Douglas Gregor5e35d592010-09-14 23:59:36 +00001838 case Sema::PCC_ObjCInterface:
1839 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001840 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001841
John McCallfaf5fb42010-08-26 23:41:50 +00001842 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001843 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001844 }
David Blaikie8a40f702012-01-17 06:56:22 +00001845
1846 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001847}
1848
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001849static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1850 const Preprocessor &PP) {
1851 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001852 Policy.AnonymousTagLocations = false;
1853 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001854 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001855 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001856 return Policy;
1857}
1858
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001859/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001860static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1861 return getCompletionPrintingPolicy(S.Context, S.PP);
1862}
1863
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001864/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001865/// that has the appropriate lifetime for code completion.
1866///
1867/// This routine provides a fast path where we provide constant strings for
1868/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001869static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001870 const PrintingPolicy &Policy,
1871 CodeCompletionAllocator &Allocator) {
1872 if (!T.getLocalQualifiers()) {
1873 // Built-in type names are constant strings.
1874 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001875 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001876
Douglas Gregore5c79d52011-10-18 21:20:17 +00001877 // Anonymous tag types are constant strings.
1878 if (const TagType *TagT = dyn_cast<TagType>(T))
1879 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001880 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001881 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001882 case TTK_Struct:
1883 return "struct <anonymous>";
1884 case TTK_Interface:
1885 return "__interface <anonymous>";
1886 case TTK_Class:
1887 return "class <anonymous>";
1888 case TTK_Union:
1889 return "union <anonymous>";
1890 case TTK_Enum:
1891 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001892 }
1893 }
1894 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001895
Douglas Gregore5c79d52011-10-18 21:20:17 +00001896 // Slow path: format the type as a string.
1897 std::string Result;
1898 T.getAsStringInternal(Result, Policy);
1899 return Allocator.CopyString(Result);
1900}
1901
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001902/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001903static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1904 QualType ThisTy = S.getCurrentThisType();
1905 if (ThisTy.isNull())
1906 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001907
Douglas Gregord8c61782012-02-15 15:34:24 +00001908 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001909 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001910 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001911 Builder.AddResultTypeChunk(
1912 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001913 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001914 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001915}
1916
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001917static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1918 ResultBuilder &Results,
1919 const LangOptions &LangOpts) {
1920 if (!LangOpts.CPlusPlus11)
1921 return;
1922
1923 Builder.AddTypedTextChunk("static_assert");
1924 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1925 Builder.AddPlaceholderChunk("expression");
1926 Builder.AddChunk(CodeCompletionString::CK_Comma);
1927 Builder.AddPlaceholderChunk("message");
1928 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov2fa31882019-05-29 15:32:17 +00001929 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001930 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1931}
1932
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001933static void AddOverrideResults(ResultBuilder &Results,
1934 const CodeCompletionContext &CCContext,
1935 CodeCompletionBuilder &Builder) {
1936 Sema &S = Results.getSema();
1937 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1938 // If not inside a class/struct/union return empty.
1939 if (!CR)
1940 return;
1941 // First store overrides within current class.
1942 // These are stored by name to make querying fast in the later step.
1943 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1944 for (auto *Method : CR->methods()) {
1945 if (!Method->isVirtual() || !Method->getIdentifier())
1946 continue;
1947 Overrides[Method->getName()].push_back(Method);
1948 }
1949
1950 for (const auto &Base : CR->bases()) {
1951 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1952 if (!BR)
1953 continue;
1954 for (auto *Method : BR->methods()) {
1955 if (!Method->isVirtual() || !Method->getIdentifier())
1956 continue;
1957 const auto it = Overrides.find(Method->getName());
1958 bool IsOverriden = false;
1959 if (it != Overrides.end()) {
1960 for (auto *MD : it->second) {
1961 // If the method in current body is not an overload of this virtual
1962 // function, then it overrides this one.
1963 if (!S.IsOverload(MD, Method, false)) {
1964 IsOverriden = true;
1965 break;
1966 }
1967 }
1968 }
1969 if (!IsOverriden) {
1970 // Generates a new CodeCompletionResult by taking this function and
1971 // converting it into an override declaration with only one chunk in the
1972 // final CodeCompletionString as a TypedTextChunk.
1973 std::string OverrideSignature;
1974 llvm::raw_string_ostream OS(OverrideSignature);
1975 CodeCompletionResult CCR(Method, 0);
1976 PrintingPolicy Policy =
1977 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1978 auto *CCS = CCR.createCodeCompletionStringForOverride(
1979 S.getPreprocessor(), S.getASTContext(), Builder,
1980 /*IncludeBriefComments=*/false, CCContext, Policy);
1981 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1982 }
1983 }
1984 }
1985}
1986
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001987/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001988static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1989 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001990 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001991 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001992
John McCall276321a2010-08-25 06:19:51 +00001993 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001994 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001995 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001996 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001997 if (Results.includeCodePatterns()) {
1998 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001999 Builder.AddTypedTextChunk("namespace");
2000 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2001 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002002 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002003 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002004 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002005 Builder.AddPlaceholderChunk("declarations");
2006 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2007 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2008 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002009 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002010
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002011 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002012 Builder.AddTypedTextChunk("namespace");
2013 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2014 Builder.AddPlaceholderChunk("name");
2015 Builder.AddChunk(CodeCompletionString::CK_Equal);
2016 Builder.AddPlaceholderChunk("namespace");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002017 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002018 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002019
2020 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002021 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2023 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002024 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002025 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002026
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002027 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002028 Builder.AddTypedTextChunk("asm");
2029 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2030 Builder.AddPlaceholderChunk("string-literal");
2031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2032 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002033
Douglas Gregorf4c33342010-05-28 00:22:41 +00002034 if (Results.includeCodePatterns()) {
2035 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002036 Builder.AddTypedTextChunk("template");
2037 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2038 Builder.AddPlaceholderChunk("declaration");
2039 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002040 } else {
2041 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00002042 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002043 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002044
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002045 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002046 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002047
Douglas Gregorf4c33342010-05-28 00:22:41 +00002048 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002049 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002050
John McCallfaf5fb42010-08-26 23:41:50 +00002051 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002052 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002053 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002054 Builder.AddTypedTextChunk("using");
2055 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2056 Builder.AddPlaceholderChunk("qualifier");
2057 Builder.AddTextChunk("::");
2058 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002059 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002060 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002061
Douglas Gregorf4c33342010-05-28 00:22:41 +00002062 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002063 if (SemaRef.CurContext->isDependentContext()) {
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002064 Builder.AddTypedTextChunk("using typename");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002065 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2066 Builder.AddPlaceholderChunk("qualifier");
2067 Builder.AddTextChunk("::");
2068 Builder.AddPlaceholderChunk("name");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002069 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002070 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002071 }
2072
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002073 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
2074
John McCallfaf5fb42010-08-26 23:41:50 +00002075 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002076 AddTypedefResult(Results);
2077
Erik Verbruggen6524c052017-10-24 13:46:58 +00002078 bool IsNotInheritanceScope =
2079 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002080 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002081 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002082 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002083 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002084 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002085
2086 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002087 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002088 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002089 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002090 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002091
2092 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002093 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00002094 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00002095 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002096 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002097
2098 // FIXME: This adds override results only if we are at the first word of
2099 // the declaration/definition. Also call this from other sides to have
2100 // more use-cases.
2101 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
2102 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002103 }
2104 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00002105 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002106
John McCallfaf5fb42010-08-26 23:41:50 +00002107 case Sema::PCC_Template:
2108 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002109 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002110 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002111 Builder.AddTypedTextChunk("template");
2112 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2113 Builder.AddPlaceholderChunk("parameters");
2114 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2115 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00002116 } else {
2117 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002118 }
2119
David Blaikiebbafb8a2012-03-11 07:00:24 +00002120 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2121 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002122 break;
2123
John McCallfaf5fb42010-08-26 23:41:50 +00002124 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002125 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
2126 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2127 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002128 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002129
John McCallfaf5fb42010-08-26 23:41:50 +00002130 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002131 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
2132 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
2133 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00002134 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002135
John McCallfaf5fb42010-08-26 23:41:50 +00002136 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002137 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00002138 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002139
John McCallfaf5fb42010-08-26 23:41:50 +00002140 case Sema::PCC_RecoveryInFunction:
2141 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00002142 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002143
David Blaikiebbafb8a2012-03-11 07:00:24 +00002144 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
2145 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002146 Builder.AddTypedTextChunk("try");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002147 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002148 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002149 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002150 Builder.AddPlaceholderChunk("statements");
2151 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2152 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002154 Builder.AddTextChunk("catch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002155 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002156 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2157 Builder.AddPlaceholderChunk("declaration");
2158 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002159 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002160 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002161 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002162 Builder.AddPlaceholderChunk("statements");
2163 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2164 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2165 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002166 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002167 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002168 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002169
Douglas Gregorf64acca2010-05-25 21:41:55 +00002170 if (Results.includeCodePatterns()) {
2171 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002172 Builder.AddTypedTextChunk("if");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002173 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002174 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002175 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002176 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002177 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002178 Builder.AddPlaceholderChunk("expression");
2179 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002180 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002181 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002182 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002183 Builder.AddPlaceholderChunk("statements");
2184 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2185 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2186 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002187
Douglas Gregorf64acca2010-05-25 21:41:55 +00002188 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002189 Builder.AddTypedTextChunk("switch");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002190 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002191 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002192 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002193 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002194 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002195 Builder.AddPlaceholderChunk("expression");
2196 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002197 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002198 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2199 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002200 Builder.AddPlaceholderChunk("cases");
2201 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002202 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2203 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002204 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002205
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002206 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00002207 if (SemaRef.getCurFunction() &&
2208 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002209 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002210 Builder.AddTypedTextChunk("case");
2211 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2212 Builder.AddPlaceholderChunk("expression");
2213 Builder.AddChunk(CodeCompletionString::CK_Colon);
2214 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002215
2216 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002217 Builder.AddTypedTextChunk("default");
2218 Builder.AddChunk(CodeCompletionString::CK_Colon);
2219 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002220 }
2221
Douglas Gregorf64acca2010-05-25 21:41:55 +00002222 if (Results.includeCodePatterns()) {
2223 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002224 Builder.AddTypedTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002225 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002226 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002227 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002228 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002229 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002230 Builder.AddPlaceholderChunk("expression");
2231 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002232 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002233 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002234 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002235 Builder.AddPlaceholderChunk("statements");
2236 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2237 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2238 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002239
2240 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002241 Builder.AddTypedTextChunk("do");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002242 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002243 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov49e432d2019-05-28 14:33:16 +00002244 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002245 Builder.AddPlaceholderChunk("statements");
2246 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2247 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2248 Builder.AddTextChunk("while");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002249 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002250 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2251 Builder.AddPlaceholderChunk("expression");
2252 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2253 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002254
Douglas Gregorf64acca2010-05-25 21:41:55 +00002255 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002256 Builder.AddTypedTextChunk("for");
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002257 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002258 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002259 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002260 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00002261 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002262 Builder.AddPlaceholderChunk("init-expression");
2263 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002264 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002265 Builder.AddPlaceholderChunk("condition");
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("inc-expression");
2269 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Ilya Biryukov1a4458452019-06-03 08:34:25 +00002270 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002271 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
2272 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2273 Builder.AddPlaceholderChunk("statements");
2274 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
2275 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
2276 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00002277 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002278
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002279 if (S->getContinueParent()) {
2280 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002281 Builder.AddTypedTextChunk("continue");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002282 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002283 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002284 }
2285
2286 if (S->getBreakParent()) {
2287 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002288 Builder.AddTypedTextChunk("break");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002289 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002290 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002291 }
2292
Ilya Biryukov32497f52019-05-27 09:52:09 +00002293 // "return expression ;" or "return ;", depending on the return type.
2294 QualType ReturnType;
Fangrui Song050229d2018-11-24 00:14:31 +00002295 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002296 ReturnType = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002297 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Ilya Biryukov32497f52019-05-27 09:52:09 +00002298 ReturnType = Method->getReturnType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002299 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00002300 !SemaRef.getCurBlock()->ReturnType.isNull())
Ilya Biryukov32497f52019-05-27 09:52:09 +00002301 ReturnType = SemaRef.getCurBlock()->ReturnType;;
2302 if (ReturnType.isNull() || ReturnType->isVoidType()) {
2303 Builder.AddTypedTextChunk("return");
2304 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2305 Results.AddResult(Result(Builder.TakeString()));
2306 } else {
2307 assert(!ReturnType.isNull());
2308 // "return expression ;"
2309 Builder.AddTypedTextChunk("return");
2310 Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002311 Builder.AddPlaceholderChunk("expression");
Ilya Biryukov32497f52019-05-27 09:52:09 +00002312 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2313 Results.AddResult(Result(Builder.TakeString()));
2314 // When boolean, also add 'return true;' and 'return false;'.
2315 if (ReturnType->isBooleanType()) {
2316 Builder.AddTypedTextChunk("return true");
2317 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2318 Results.AddResult(Result(Builder.TakeString()));
2319
2320 Builder.AddTypedTextChunk("return false");
2321 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
2322 Results.AddResult(Result(Builder.TakeString()));
2323 }
Douglas Gregor44272ca2010-02-18 04:06:48 +00002324 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002325
Douglas Gregorf4c33342010-05-28 00:22:41 +00002326 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002327 Builder.AddTypedTextChunk("goto");
2328 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2329 Builder.AddPlaceholderChunk("label");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002330 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002331 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002332
Douglas Gregorf4c33342010-05-28 00:22:41 +00002333 // Using directives
Ilya Biryukov30977fc2019-06-04 09:26:08 +00002334 Builder.AddTypedTextChunk("using namespace");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002335 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2336 Builder.AddPlaceholderChunk("identifier");
Ilya Biryukov15a37eb2019-05-06 13:18:00 +00002337 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002338 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002339
2340 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002341 }
Fangrui Song050229d2018-11-24 00:14:31 +00002342 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002343
2344 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002345 case Sema::PCC_ForInit:
2346 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002347 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002348 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002349 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002350
Douglas Gregor5e35d592010-09-14 23:59:36 +00002351 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002352 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002353 CCC == Sema::PCC_ParenthesizedExpression) {
2354 // (__bridge <type>)<expression>
2355 Builder.AddTypedTextChunk("__bridge");
2356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2357 Builder.AddPlaceholderChunk("type");
2358 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2359 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002360 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002361
2362 // (__bridge_transfer <Objective-C type>)<expression>
2363 Builder.AddTypedTextChunk("__bridge_transfer");
2364 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2365 Builder.AddPlaceholderChunk("Objective-C type");
2366 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2367 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002368 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002369
2370 // (__bridge_retained <CF type>)<expression>
2371 Builder.AddTypedTextChunk("__bridge_retained");
2372 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2373 Builder.AddPlaceholderChunk("CF type");
2374 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2375 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002376 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002377 }
2378 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002379 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002380
John McCallfaf5fb42010-08-26 23:41:50 +00002381 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002382 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002383 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002384 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002385
Douglas Gregore5c79d52011-10-18 21:20:17 +00002386 // true
2387 Builder.AddResultTypeChunk("bool");
2388 Builder.AddTypedTextChunk("true");
2389 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002390
Douglas Gregore5c79d52011-10-18 21:20:17 +00002391 // false
2392 Builder.AddResultTypeChunk("bool");
2393 Builder.AddTypedTextChunk("false");
2394 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002395
David Blaikiebbafb8a2012-03-11 07:00:24 +00002396 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002397 // dynamic_cast < type-id > ( expression )
2398 Builder.AddTypedTextChunk("dynamic_cast");
2399 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2400 Builder.AddPlaceholderChunk("type");
2401 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2402 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2403 Builder.AddPlaceholderChunk("expression");
2404 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002405 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002406 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002407
Douglas Gregorf4c33342010-05-28 00:22:41 +00002408 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002409 Builder.AddTypedTextChunk("static_cast");
2410 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2411 Builder.AddPlaceholderChunk("type");
2412 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2413 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2414 Builder.AddPlaceholderChunk("expression");
2415 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002416 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002417
Douglas Gregorf4c33342010-05-28 00:22:41 +00002418 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002419 Builder.AddTypedTextChunk("reinterpret_cast");
2420 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2421 Builder.AddPlaceholderChunk("type");
2422 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2423 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2424 Builder.AddPlaceholderChunk("expression");
2425 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002426 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002427
Douglas Gregorf4c33342010-05-28 00:22:41 +00002428 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002429 Builder.AddTypedTextChunk("const_cast");
2430 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2431 Builder.AddPlaceholderChunk("type");
2432 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2433 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2434 Builder.AddPlaceholderChunk("expression");
2435 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002436 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002437
David Blaikiebbafb8a2012-03-11 07:00:24 +00002438 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002439 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002440 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002441 Builder.AddTypedTextChunk("typeid");
2442 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2443 Builder.AddPlaceholderChunk("expression-or-type");
2444 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002445 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002446 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002447
Douglas Gregorf4c33342010-05-28 00:22:41 +00002448 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002449 Builder.AddTypedTextChunk("new");
2450 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2451 Builder.AddPlaceholderChunk("type");
2452 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2453 Builder.AddPlaceholderChunk("expressions");
2454 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002455 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002456
Douglas Gregorf4c33342010-05-28 00:22:41 +00002457 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002458 Builder.AddTypedTextChunk("new");
2459 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2460 Builder.AddPlaceholderChunk("type");
2461 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2462 Builder.AddPlaceholderChunk("size");
2463 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2464 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2465 Builder.AddPlaceholderChunk("expressions");
2466 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002467 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002468
Douglas Gregorf4c33342010-05-28 00:22:41 +00002469 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002470 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002471 Builder.AddTypedTextChunk("delete");
2472 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2473 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002474 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002475
Douglas Gregorf4c33342010-05-28 00:22:41 +00002476 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002477 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002478 Builder.AddTypedTextChunk("delete");
2479 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2480 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2481 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2482 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2483 Builder.AddPlaceholderChunk("expression");
2484 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002485
David Blaikiebbafb8a2012-03-11 07:00:24 +00002486 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002487 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002488 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002489 Builder.AddTypedTextChunk("throw");
2490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2491 Builder.AddPlaceholderChunk("expression");
2492 Results.AddResult(Result(Builder.TakeString()));
2493 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002494
Douglas Gregora2db7932010-05-26 22:00:08 +00002495 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002496
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002497 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002498 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002499 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002500 Builder.AddTypedTextChunk("nullptr");
2501 Results.AddResult(Result(Builder.TakeString()));
2502
2503 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002504 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002505 Builder.AddTypedTextChunk("alignof");
2506 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2507 Builder.AddPlaceholderChunk("type");
2508 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2509 Results.AddResult(Result(Builder.TakeString()));
2510
2511 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002512 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002513 Builder.AddTypedTextChunk("noexcept");
2514 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2515 Builder.AddPlaceholderChunk("expression");
2516 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2517 Results.AddResult(Result(Builder.TakeString()));
2518
2519 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002520 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002521 Builder.AddTypedTextChunk("sizeof...");
2522 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2523 Builder.AddPlaceholderChunk("parameter-pack");
2524 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2525 Results.AddResult(Result(Builder.TakeString()));
2526 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002527 }
2528
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002529 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002530 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002531 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2532 // The interface can be NULL.
2533 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002534 if (ID->getSuperClass()) {
2535 std::string SuperType;
2536 SuperType = ID->getSuperClass()->getNameAsString();
2537 if (Method->isInstanceMethod())
2538 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002539
Douglas Gregore5c79d52011-10-18 21:20:17 +00002540 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2541 Builder.AddTypedTextChunk("super");
2542 Results.AddResult(Result(Builder.TakeString()));
2543 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002544 }
2545
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002546 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002547 }
2548
Jordan Rose58d54722012-06-30 21:33:57 +00002549 if (SemaRef.getLangOpts().C11) {
2550 // _Alignof
2551 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002552 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002553 Builder.AddTypedTextChunk("alignof");
2554 else
2555 Builder.AddTypedTextChunk("_Alignof");
2556 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2557 Builder.AddPlaceholderChunk("type");
2558 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2559 Results.AddResult(Result(Builder.TakeString()));
2560 }
2561
Douglas Gregorf4c33342010-05-28 00:22:41 +00002562 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002563 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002564 Builder.AddTypedTextChunk("sizeof");
2565 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2566 Builder.AddPlaceholderChunk("expression-or-type");
2567 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2568 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002569 break;
2570 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002571
John McCallfaf5fb42010-08-26 23:41:50 +00002572 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002573 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002574 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002575 }
2576
David Blaikiebbafb8a2012-03-11 07:00:24 +00002577 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2578 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002579
David Blaikiebbafb8a2012-03-11 07:00:24 +00002580 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002581 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002582}
2583
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002584/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002585/// type chunk.
2586static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002587 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002588 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002589 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002590 if (!ND)
2591 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002592
2593 // Skip constructors and conversion functions, which have their return types
2594 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002595 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002596 return;
2597
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002598 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002599 QualType T;
2600 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002601 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002602 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002603 if (!BaseType.isNull())
2604 T = Method->getSendResultType(BaseType);
2605 else
2606 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002607 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002608 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002609 T = clang::TypeName::getFullyQualifiedType(T, Context);
2610 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002611 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002612 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002613 if (!BaseType.isNull())
2614 T = Ivar->getUsageType(BaseType);
2615 else
2616 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002617 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002618 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002619 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002620 if (!BaseType.isNull())
2621 T = Property->getUsageType(BaseType);
2622 else
2623 T = Property->getType();
2624 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002625
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002626 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2627 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002628
Fangrui Song050229d2018-11-24 00:14:31 +00002629 Result.AddResultTypeChunk(
2630 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002631}
2632
Richard Smith20e883e2015-04-29 23:20:19 +00002633static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002634 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002635 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002636 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2637 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002638 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002639 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002640 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002641 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002642 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002643 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002644 }
2645}
2646
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002647static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002648 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002649 std::string Result;
2650 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002651 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002652 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002653 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002654 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002655 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002656 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002657 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002658 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002659 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002660 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002661 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002662 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2663 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2664 switch (*nullability) {
2665 case NullabilityKind::NonNull:
2666 Result += "nonnull ";
2667 break;
2668
2669 case NullabilityKind::Nullable:
2670 Result += "nullable ";
2671 break;
2672
2673 case NullabilityKind::Unspecified:
2674 Result += "null_unspecified ";
2675 break;
2676 }
2677 }
2678 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002679 return Result;
2680}
2681
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002682/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002683/// block placeholder.
2684///
2685/// This function ignores things like typedefs and qualifiers in order to
2686/// present the most relevant and accurate block placeholders in code completion
2687/// results.
2688static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2689 FunctionTypeLoc &Block,
2690 FunctionProtoTypeLoc &BlockProto,
2691 bool SuppressBlock = false) {
2692 if (!TSInfo)
2693 return;
2694 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2695 while (true) {
2696 // Look through typedefs.
2697 if (!SuppressBlock) {
2698 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2699 if (TypeSourceInfo *InnerTSInfo =
2700 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2701 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2702 continue;
2703 }
2704 }
2705
2706 // Look through qualified types
2707 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2708 TL = QualifiedTL.getUnqualifiedLoc();
2709 continue;
2710 }
2711
2712 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2713 TL = AttrTL.getModifiedLoc();
2714 continue;
2715 }
2716 }
2717
2718 // Try to get the function prototype behind the block pointer type,
2719 // then we're done.
2720 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2721 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2722 Block = TL.getAs<FunctionTypeLoc>();
2723 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2724 }
2725 break;
2726 }
2727}
2728
Alex Lorenz920ae142016-10-18 10:38:58 +00002729static std::string
2730formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2731 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002732 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002733 bool SuppressBlock = false,
2734 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2735
Fangrui Song050229d2018-11-24 00:14:31 +00002736static std::string
2737FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2738 bool SuppressName = false, bool SuppressBlock = false,
2739 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Sam McCallbc7ff892019-04-04 11:34:18 +00002740 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid.
2741 // It would be better to pass in the param Type, which is usually avaliable.
2742 // But this case is rare, so just pretend we fell back to int as elsewhere.
2743 if (!Param)
2744 return "int";
Douglas Gregore90dd002010-08-24 16:15:59 +00002745 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2746 if (Param->getType()->isDependentType() ||
2747 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002748 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002749 // containing that parameter's type.
2750 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002751
Douglas Gregor981a0c42010-08-29 19:47:46 +00002752 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002753 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002754
Douglas Gregor86b42682015-06-19 18:27:52 +00002755 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002756 if (ObjCSubsts)
2757 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2758 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002759 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002760 Result =
2761 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002762 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002763 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002764 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002765 } else {
2766 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002767 }
2768 return Result;
2769 }
Alex Lorenza1951202016-10-18 10:35:27 +00002770
Douglas Gregore90dd002010-08-24 16:15:59 +00002771 // The argument for a block pointer parameter is a block literal with
2772 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002773 FunctionTypeLoc Block;
2774 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002775 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2776 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002777 // Try to retrieve the block type information from the property if this is a
2778 // parameter in a setter.
2779 if (!Block && ObjCMethodParam &&
2780 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2781 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2782 ->findPropertyDecl(/*CheckOverrides=*/false))
2783 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2784 SuppressBlock);
2785 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002786
2787 if (!Block) {
2788 // We were unable to find a FunctionProtoTypeLoc with parameter names
2789 // for the block; just use the parameter type as a placeholder.
2790 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002791 if (!ObjCMethodParam && Param->getIdentifier())
2792 Result = Param->getIdentifier()->getName();
2793
Douglas Gregor86b42682015-06-19 18:27:52 +00002794 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002795
Douglas Gregore90dd002010-08-24 16:15:59 +00002796 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002797 Result = Type.getAsString(Policy);
2798 std::string Quals =
2799 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2800 if (!Quals.empty())
2801 Result = "(" + Quals + " " + Result + ")";
2802 if (Result.back() != ')')
2803 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002804 if (Param->getIdentifier())
2805 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002806 } else {
2807 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002808 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002809
Douglas Gregore90dd002010-08-24 16:15:59 +00002810 return Result;
2811 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002812
Douglas Gregore90dd002010-08-24 16:15:59 +00002813 // We have the function prototype behind the block pointer type, as it was
2814 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002815 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2816 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002817 ObjCSubsts);
2818}
2819
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002820/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002821/// declaration.
2822///
2823/// \param BlockDecl A declaration with an Objective-C block type.
2824///
2825/// \param Block The most relevant type location for that block type.
2826///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002827/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002828/// declaration is included in the resulting string.
2829static std::string
2830formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2831 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002832 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002833 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002834 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002835 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002836 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002837 ResultType =
2838 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2839 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002840 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002841 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002842
2843 // Format the parameter list.
2844 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002845 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002846 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002847 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002848 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002849 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002850 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002851 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002852 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002853 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002854 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002855 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002856 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002857 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002858
David Blaikie6adc78e2013-02-18 22:06:02 +00002859 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002860 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002861 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002862 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002863 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002864
Douglas Gregord793e7c2011-10-18 04:23:19 +00002865 if (SuppressBlock) {
2866 // Format as a parameter.
2867 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002868 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002869 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002870 Result += ")";
2871 Result += Params;
2872 } else {
2873 // Format as a block literal argument.
2874 Result = '^' + Result;
2875 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002876
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002877 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002878 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002879 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002880
Douglas Gregore90dd002010-08-24 16:15:59 +00002881 return Result;
2882}
2883
Erik Verbruggen11338c52017-07-19 10:45:40 +00002884static std::string GetDefaultValueString(const ParmVarDecl *Param,
2885 const SourceManager &SM,
2886 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002887 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002888 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2889 bool Invalid = CharSrcRange.isInvalid();
2890 if (Invalid)
2891 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002892 StringRef srcText =
2893 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002894 if (Invalid)
2895 return "";
2896
2897 if (srcText.empty() || srcText == "=") {
2898 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002899 // This happens if the code is incorrect (for example class is forward
2900 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002901 return "";
2902 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002903 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002904 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2905 // this value always has (or always does not have) '=' in front of it
2906 if (DefValue.at(0) != '=') {
2907 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002908 // Lexer returns built-in types values without '=' and user-defined types
2909 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002910 return " = " + DefValue;
2911 }
2912 return " " + DefValue;
2913}
2914
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002915/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002916static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002917 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002918 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002919 CodeCompletionBuilder &Result,
2920 unsigned Start = 0,
2921 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002922 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002923
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002924 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002925 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002926
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002927 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002928 // When we see an optional default argument, put that argument and
2929 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002930 CodeCompletionBuilder Opt(Result.getAllocator(),
2931 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002932 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002933 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002934 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002935 Result.AddOptionalChunk(Opt.TakeString());
2936 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002937 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002938
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002939 if (FirstParameter)
2940 FirstParameter = false;
2941 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002942 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002943
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002944 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002945
Douglas Gregor3545ff42009-09-21 16:56:56 +00002946 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002947 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002948 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002949 PlaceholderStr +=
2950 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002951
Douglas Gregor400f5972010-08-31 05:13:43 +00002952 if (Function->isVariadic() && P == N - 1)
2953 PlaceholderStr += ", ...";
2954
Douglas Gregor3545ff42009-09-21 16:56:56 +00002955 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002956 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002957 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002958 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002959
Fangrui Song050229d2018-11-24 00:14:31 +00002960 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002961 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002962 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002963 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002964
Richard Smith20e883e2015-04-29 23:20:19 +00002965 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002966 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002967}
2968
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002969/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002970static void AddTemplateParameterChunks(
2971 ASTContext &Context, const PrintingPolicy &Policy,
2972 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2973 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002974 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002975
2976 // Prefer to take the template parameter names from the first declaration of
2977 // the template.
2978 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2979
Douglas Gregor3545ff42009-09-21 16:56:56 +00002980 TemplateParameterList *Params = Template->getTemplateParameters();
2981 TemplateParameterList::iterator PEnd = Params->end();
2982 if (MaxParameters)
2983 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002984 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2985 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002986 bool HasDefaultArg = false;
2987 std::string PlaceholderStr;
2988 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2989 if (TTP->wasDeclaredWithTypename())
2990 PlaceholderStr = "typename";
2991 else
2992 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002993
Douglas Gregor3545ff42009-09-21 16:56:56 +00002994 if (TTP->getIdentifier()) {
2995 PlaceholderStr += ' ';
2996 PlaceholderStr += TTP->getIdentifier()->getName();
2997 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002998
Douglas Gregor3545ff42009-09-21 16:56:56 +00002999 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003000 } else if (NonTypeTemplateParmDecl *NTTP =
3001 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003002 if (NTTP->getIdentifier())
3003 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00003004 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003005 HasDefaultArg = NTTP->hasDefaultArgument();
3006 } else {
3007 assert(isa<TemplateTemplateParmDecl>(*P));
3008 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003009
Douglas Gregor3545ff42009-09-21 16:56:56 +00003010 // Since putting the template argument list into the placeholder would
3011 // be very, very long, we just use an abbreviation.
3012 PlaceholderStr = "template<...> class";
3013 if (TTP->getIdentifier()) {
3014 PlaceholderStr += ' ';
3015 PlaceholderStr += TTP->getIdentifier()->getName();
3016 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003017
Douglas Gregor3545ff42009-09-21 16:56:56 +00003018 HasDefaultArg = TTP->hasDefaultArgument();
3019 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003020
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003021 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003022 // When we see an optional default argument, put that argument and
3023 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003024 CodeCompletionBuilder Opt(Result.getAllocator(),
3025 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003026 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003027 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00003028 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003029 P - Params->begin(), true);
3030 Result.AddOptionalChunk(Opt.TakeString());
3031 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003032 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003033
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003034 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003035
Douglas Gregor3545ff42009-09-21 16:56:56 +00003036 if (FirstParameter)
3037 FirstParameter = false;
3038 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003039 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003040
Douglas Gregor3545ff42009-09-21 16:56:56 +00003041 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003042 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003043 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003044 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003045}
3046
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003047/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00003048/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00003049static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
3050 NestedNameSpecifier *Qualifier,
3051 bool QualifierIsInformative,
3052 ASTContext &Context,
3053 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003054 if (!Qualifier)
3055 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003056
Douglas Gregorf2510672009-09-21 19:57:38 +00003057 std::string PrintedNNS;
3058 {
3059 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00003060 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00003061 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00003062 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003063 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00003064 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003065 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00003066}
3067
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003068static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003069AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003070 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00003071 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003072 if (!Proto || !Proto->getMethodQuals())
Douglas Gregor0f622362009-12-11 18:44:16 +00003073 return;
3074
Douglas Gregor304f9b02011-02-01 21:15:40 +00003075 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003076
Douglas Gregor304f9b02011-02-01 21:15:40 +00003077 // Handle single qualifiers without copying
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003078 if (Proto->getMethodQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003079 Result.AddInformativeChunk(" const");
3080 return;
3081 }
3082
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003083 if (Proto->getMethodQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003084 Result.AddInformativeChunk(" volatile");
3085 return;
3086 }
3087
Anastasia Stulovac61eaa52019-01-28 11:37:49 +00003088 if (Proto->getMethodQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00003089 Result.AddInformativeChunk(" restrict");
3090 return;
3091 }
3092
3093 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00003094 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00003095 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00003096 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00003097 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00003098 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00003099 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00003100 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003101 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00003102}
3103
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003104/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00003105static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003106 const NamedDecl *ND,
3107 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00003108 DeclarationName Name = ND->getDeclName();
3109 if (!Name)
3110 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003111
Douglas Gregor0212fd72010-09-21 16:06:22 +00003112 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003113 case DeclarationName::CXXOperatorName: {
3114 const char *OperatorName = nullptr;
3115 switch (Name.getCXXOverloadedOperator()) {
3116 case OO_None:
3117 case OO_Conditional:
3118 case NUM_OVERLOADED_OPERATORS:
3119 OperatorName = "operator";
3120 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003121
Fangrui Song050229d2018-11-24 00:14:31 +00003122#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
3123 case OO_##Name: \
3124 OperatorName = "operator" Spelling; \
3125 break;
3126#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00003127#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003128
Fangrui Song050229d2018-11-24 00:14:31 +00003129 case OO_New:
3130 OperatorName = "operator new";
3131 break;
3132 case OO_Delete:
3133 OperatorName = "operator delete";
3134 break;
3135 case OO_Array_New:
3136 OperatorName = "operator new[]";
3137 break;
3138 case OO_Array_Delete:
3139 OperatorName = "operator delete[]";
3140 break;
3141 case OO_Call:
3142 OperatorName = "operator()";
3143 break;
3144 case OO_Subscript:
3145 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00003146 break;
3147 }
Fangrui Song050229d2018-11-24 00:14:31 +00003148 Result.AddTypedTextChunk(OperatorName);
3149 break;
3150 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003151
Douglas Gregor0212fd72010-09-21 16:06:22 +00003152 case DeclarationName::Identifier:
3153 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003154 case DeclarationName::CXXDestructorName:
3155 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003156 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003157 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003158 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003159
Richard Smith35845152017-02-07 01:37:30 +00003160 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00003161 case DeclarationName::CXXUsingDirective:
3162 case DeclarationName::ObjCZeroArgSelector:
3163 case DeclarationName::ObjCOneArgSelector:
3164 case DeclarationName::ObjCMultiArgSelector:
3165 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003166
Douglas Gregor0212fd72010-09-21 16:06:22 +00003167 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00003168 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00003169 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00003170 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003171 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00003172 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00003173 Record = InjectedTy->getDecl();
3174 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003175 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003176 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003177 break;
3178 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003179
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003180 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003181 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00003182 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003183 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00003184 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003185 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003186 }
3187 break;
3188 }
3189 }
3190}
3191
Fangrui Song050229d2018-11-24 00:14:31 +00003192CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3193 Sema &S, const CodeCompletionContext &CCContext,
3194 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3195 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003196 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
3197 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003198}
3199
Eric Liu00f43c92018-07-06 09:43:57 +00003200CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
3201 Preprocessor &PP, CodeCompletionAllocator &Allocator,
3202 CodeCompletionTUInfo &CCTUInfo) {
3203 assert(Kind == RK_Macro);
3204 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
3205 const MacroInfo *MI = PP.getMacroInfo(Macro);
3206 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
3207
3208 if (!MI || !MI->isFunctionLike())
3209 return Result.TakeString();
3210
3211 // Format a function-like macro with placeholders for the arguments.
3212 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3213 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
3214
3215 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
3216 if (MI->isC99Varargs()) {
3217 --AEnd;
3218
3219 if (A == AEnd) {
3220 Result.AddPlaceholderChunk("...");
3221 }
3222 }
3223
3224 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
3225 if (A != MI->param_begin())
3226 Result.AddChunk(CodeCompletionString::CK_Comma);
3227
3228 if (MI->isVariadic() && (A + 1) == AEnd) {
3229 SmallString<32> Arg = (*A)->getName();
3230 if (MI->isC99Varargs())
3231 Arg += ", ...";
3232 else
3233 Arg += "...";
3234 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
3235 break;
3236 }
3237
3238 // Non-variadic macros are simple.
3239 Result.AddPlaceholderChunk(
3240 Result.getAllocator().CopyString((*A)->getName()));
3241 }
3242 Result.AddChunk(CodeCompletionString::CK_RightParen);
3243 return Result.TakeString();
3244}
3245
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003246/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00003247/// result.
3248///
3249/// \returns Either a new, heap-allocated code completion string describing
3250/// how to use this result, or NULL to indicate that the string or name of the
3251/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00003252CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
3253 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
3254 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
3255 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00003256 if (Kind == RK_Macro)
3257 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
3258
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003259 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003260
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003261 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003262 if (Kind == RK_Pattern) {
3263 Pattern->Priority = Priority;
3264 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003265
Douglas Gregor78254c82012-03-27 23:34:16 +00003266 if (Declaration) {
3267 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00003268 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003269 if (const RawComment *RC =
3270 getPatternCompletionComment(Ctx, Declaration)) {
3271 Result.addBriefComment(RC->getBriefText(Ctx));
3272 Pattern->BriefComment = Result.getBriefComment();
3273 }
Douglas Gregor78254c82012-03-27 23:34:16 +00003274 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003275
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003276 return Pattern;
3277 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003278
Douglas Gregorf09935f2009-12-01 05:55:20 +00003279 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003280 Result.AddTypedTextChunk(Keyword);
3281 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00003282 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00003283 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00003284 return createCodeCompletionStringForDecl(
3285 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003286}
3287
Ilya Biryukovcabab292019-05-24 10:18:39 +00003288static void printOverrideString(const CodeCompletionString &CCS,
3289 std::string &BeforeName,
3290 std::string &NameAndSignature) {
3291 bool SeenTypedChunk = false;
3292 for (auto &Chunk : CCS) {
3293 if (Chunk.Kind == CodeCompletionString::CK_Optional) {
3294 assert(SeenTypedChunk && "optional parameter before name");
3295 // Note that we put all chunks inside into NameAndSignature.
3296 printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature);
3297 continue;
3298 }
3299 SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText;
3300 if (SeenTypedChunk)
3301 NameAndSignature += Chunk.Text;
3302 else
3303 BeforeName += Chunk.Text;
3304 }
3305}
3306
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003307CodeCompletionString *
3308CodeCompletionResult::createCodeCompletionStringForOverride(
3309 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3310 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3311 PrintingPolicy &Policy) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003312 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
3313 /*IncludeBriefComments=*/false,
3314 CCContext, Policy);
Ilya Biryukovcabab292019-05-24 10:18:39 +00003315 std::string BeforeName;
3316 std::string NameAndSignature;
3317 // For overrides all chunks go into the result, none are informative.
3318 printOverrideString(*CCS, BeforeName, NameAndSignature);
3319 NameAndSignature += " override";
3320
3321 Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));
3322 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3323 Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003324 return Result.TakeString();
3325}
3326
3327CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
3328 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
3329 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
3330 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003331 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00003332 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003333
3334 if (IncludeBriefComments) {
3335 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003336 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003337 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003338 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00003339 }
3340
Douglas Gregor9eb77012009-11-07 00:00:49 +00003341 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003342 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003343 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003344 Result.AddTextChunk("::");
3345 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00003346 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00003347
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00003348 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
3349 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00003350
Douglas Gregorc3425b12015-07-07 06:20:19 +00003351 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003352
Fangrui Song050229d2018-11-24 00:14:31 +00003353 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003354 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003355 Ctx, Policy);
3356 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003357 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003358 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003359 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003360 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003361 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003362 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003363
Fangrui Song050229d2018-11-24 00:14:31 +00003364 if (const FunctionTemplateDecl *FunTmpl =
3365 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003366 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003367 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003368 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003369 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003370
Douglas Gregor3545ff42009-09-21 16:56:56 +00003371 // Figure out which template parameters are deduced (or have default
3372 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003373 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003374 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003375 unsigned LastDeducibleArgument;
3376 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3377 --LastDeducibleArgument) {
3378 if (!Deduced[LastDeducibleArgument - 1]) {
3379 // C++0x: Figure out if the template argument has a default. If so,
3380 // the user doesn't need to type this argument.
3381 // FIXME: We need to abstract template parameters better!
3382 bool HasDefaultArg = false;
3383 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003384 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003385 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3386 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003387 else if (NonTypeTemplateParmDecl *NTTP =
3388 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003389 HasDefaultArg = NTTP->hasDefaultArgument();
3390 else {
3391 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003392 HasDefaultArg =
3393 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003394 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003395
Douglas Gregor3545ff42009-09-21 16:56:56 +00003396 if (!HasDefaultArg)
3397 break;
3398 }
3399 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003400
Douglas Gregor3545ff42009-09-21 16:56:56 +00003401 if (LastDeducibleArgument) {
3402 // Some of the function template arguments cannot be deduced from a
3403 // function call, so we introduce an explicit template argument list
3404 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003405 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003406 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003407 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003408 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003409 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003410
Douglas Gregor3545ff42009-09-21 16:56:56 +00003411 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003412 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003413 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003414 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003415 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003416 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003417 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003418
Fangrui Song050229d2018-11-24 00:14:31 +00003419 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003420 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003421 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003422 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003423 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003424 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003425 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003426 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003427 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003428 }
Fangrui Song050229d2018-11-24 00:14:31 +00003429 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003430 Selector Sel = Method->getSelector();
3431 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003432 Result.AddTypedTextChunk(
3433 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003434 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003435 }
3436
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003437 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003438 SelName += ':';
3439 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003440 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003441 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003442 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003443
Douglas Gregor1b605f72009-11-19 01:08:35 +00003444 // If there is only one parameter, and we're past it, add an empty
3445 // typed-text chunk since there is nothing to type.
3446 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003447 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003448 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003449 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003450 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003451 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003452 P != PEnd; (void)++P, ++Idx) {
3453 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003454 std::string Keyword;
3455 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003456 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003457 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003458 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003459 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003460 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003461 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003462 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003463 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003464 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003465
Douglas Gregor1b605f72009-11-19 01:08:35 +00003466 // If we're before the starting parameter, skip the placeholder.
3467 if (Idx < StartParameter)
3468 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003469
3470 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003471 QualType ParamType = (*P)->getType();
3472 Optional<ArrayRef<QualType>> ObjCSubsts;
3473 if (!CCContext.getBaseType().isNull())
3474 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3475
3476 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3477 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003478 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003479 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003480 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003481 ParamType = ParamType.substObjCTypeArgs(
3482 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003483 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003484 ParamType);
3485 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003486 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003487 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003488 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003489 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003490
Douglas Gregor400f5972010-08-31 05:13:43 +00003491 if (Method->isVariadic() && (P + 1) == PEnd)
3492 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003493
Douglas Gregor95887f92010-07-08 23:20:03 +00003494 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003495 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003496 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003497 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003498 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003499 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003500 }
3501
Douglas Gregor04c5f972009-12-23 00:21:46 +00003502 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003503 if (Method->param_size() == 0) {
3504 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003505 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003506 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003507 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003508 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003509 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003510 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003511
Richard Smith20e883e2015-04-29 23:20:19 +00003512 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003513 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003514
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003515 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003516 }
3517
Douglas Gregorf09935f2009-12-01 05:55:20 +00003518 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003519 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003520 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003521
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003522 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003523 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003524 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003525}
3526
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003527const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3528 const NamedDecl *ND) {
3529 if (!ND)
3530 return nullptr;
3531 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3532 return RC;
3533
3534 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003535 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003536 if (!M)
3537 return nullptr;
3538 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3539 if (!PDecl)
3540 return nullptr;
3541
3542 return Ctx.getRawCommentForAnyRedecl(PDecl);
3543}
3544
3545const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3546 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003547 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003548 if (!M || !M->isPropertyAccessor())
3549 return nullptr;
3550
3551 // Provide code completion comment for self.GetterName where
3552 // GetterName is the getter method for a property with name
3553 // different from the property name (declared via a property
3554 // getter attribute.
3555 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3556 if (!PDecl)
3557 return nullptr;
3558 if (PDecl->getGetterName() == M->getSelector() &&
3559 PDecl->getIdentifier() != M->getIdentifier()) {
3560 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3561 return RC;
3562 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3563 return RC;
3564 }
3565 return nullptr;
3566}
3567
3568const RawComment *clang::getParameterComment(
3569 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003570 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003571 auto FDecl = Result.getFunction();
3572 if (!FDecl)
3573 return nullptr;
3574 if (ArgIndex < FDecl->getNumParams())
3575 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3576 return nullptr;
3577}
3578
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003579/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003580/// string.
3581static void AddOverloadParameterChunks(ASTContext &Context,
3582 const PrintingPolicy &Policy,
3583 const FunctionDecl *Function,
3584 const FunctionProtoType *Prototype,
3585 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003586 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003587 bool InOptional = false) {
3588 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003589 unsigned NumParams =
3590 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003591
3592 for (unsigned P = Start; P != NumParams; ++P) {
3593 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3594 // When we see an optional default argument, put that argument and
3595 // the remaining default arguments into a new, optional string.
3596 CodeCompletionBuilder Opt(Result.getAllocator(),
3597 Result.getCodeCompletionTUInfo());
3598 if (!FirstParameter)
3599 Opt.AddChunk(CodeCompletionString::CK_Comma);
3600 // Optional sections are nested.
3601 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3602 CurrentArg, P, /*InOptional=*/true);
3603 Result.AddOptionalChunk(Opt.TakeString());
3604 return;
3605 }
3606
3607 if (FirstParameter)
3608 FirstParameter = false;
3609 else
3610 Result.AddChunk(CodeCompletionString::CK_Comma);
3611
3612 InOptional = false;
3613
3614 // Format the placeholder string.
3615 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003616 if (Function) {
3617 const ParmVarDecl *Param = Function->getParamDecl(P);
3618 Placeholder = FormatFunctionParameter(Policy, Param);
3619 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003620 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3621 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003622 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003623 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003624 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003625
3626 if (P == CurrentArg)
3627 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003628 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003629 else
3630 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3631 }
3632
3633 if (Prototype && Prototype->isVariadic()) {
3634 CodeCompletionBuilder Opt(Result.getAllocator(),
3635 Result.getCodeCompletionTUInfo());
3636 if (!FirstParameter)
3637 Opt.AddChunk(CodeCompletionString::CK_Comma);
3638
3639 if (CurrentArg < NumParams)
3640 Opt.AddPlaceholderChunk("...");
3641 else
3642 Opt.AddCurrentParameterChunk("...");
3643
3644 Result.AddOptionalChunk(Opt.TakeString());
3645 }
3646}
3647
Douglas Gregorf0f51982009-09-23 00:34:09 +00003648CodeCompletionString *
3649CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003650 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3651 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003652 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003653
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003654 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003655 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3656 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003657 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003658 const FunctionProtoType *Proto =
3659 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003660 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003661 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003662 // highlighted ellipsis.
3663 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003664 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003665 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003666 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3667 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3668 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003669 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003670 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003671
3672 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003673 if (IncludeBriefComments) {
3674 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003675 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003676 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003677 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003678 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003679 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003680 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003681 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003682 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003683 }
Alp Toker314cc812014-01-25 16:55:45 +00003684
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003685 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003686 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3687 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003688 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003689
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003690 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003691}
3692
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003693unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003694 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003695 bool PreferredTypeIsPointer) {
3696 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003697
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003698 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003699 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003700 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003701 Priority = CCP_Constant;
3702 if (PreferredTypeIsPointer)
3703 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003704 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003705 // Treat "YES", "NO", "true", and "false" as constants.
3706 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3707 MacroName.equals("true") || MacroName.equals("false"))
3708 Priority = CCP_Constant;
3709 // Treat "bool" as a type.
3710 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003711 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003712
Douglas Gregor6e240332010-08-16 16:18:59 +00003713 return Priority;
3714}
3715
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003716CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003717 if (!D)
3718 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003719
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003720 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003721 case Decl::Enum:
3722 return CXCursor_EnumDecl;
3723 case Decl::EnumConstant:
3724 return CXCursor_EnumConstantDecl;
3725 case Decl::Field:
3726 return CXCursor_FieldDecl;
3727 case Decl::Function:
3728 return CXCursor_FunctionDecl;
3729 case Decl::ObjCCategory:
3730 return CXCursor_ObjCCategoryDecl;
3731 case Decl::ObjCCategoryImpl:
3732 return CXCursor_ObjCCategoryImplDecl;
3733 case Decl::ObjCImplementation:
3734 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003735
Fangrui Song050229d2018-11-24 00:14:31 +00003736 case Decl::ObjCInterface:
3737 return CXCursor_ObjCInterfaceDecl;
3738 case Decl::ObjCIvar:
3739 return CXCursor_ObjCIvarDecl;
3740 case Decl::ObjCMethod:
3741 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3742 ? CXCursor_ObjCInstanceMethodDecl
3743 : CXCursor_ObjCClassMethodDecl;
3744 case Decl::CXXMethod:
3745 return CXCursor_CXXMethod;
3746 case Decl::CXXConstructor:
3747 return CXCursor_Constructor;
3748 case Decl::CXXDestructor:
3749 return CXCursor_Destructor;
3750 case Decl::CXXConversion:
3751 return CXCursor_ConversionFunction;
3752 case Decl::ObjCProperty:
3753 return CXCursor_ObjCPropertyDecl;
3754 case Decl::ObjCProtocol:
3755 return CXCursor_ObjCProtocolDecl;
3756 case Decl::ParmVar:
3757 return CXCursor_ParmDecl;
3758 case Decl::Typedef:
3759 return CXCursor_TypedefDecl;
3760 case Decl::TypeAlias:
3761 return CXCursor_TypeAliasDecl;
3762 case Decl::TypeAliasTemplate:
3763 return CXCursor_TypeAliasTemplateDecl;
3764 case Decl::Var:
3765 return CXCursor_VarDecl;
3766 case Decl::Namespace:
3767 return CXCursor_Namespace;
3768 case Decl::NamespaceAlias:
3769 return CXCursor_NamespaceAlias;
3770 case Decl::TemplateTypeParm:
3771 return CXCursor_TemplateTypeParameter;
3772 case Decl::NonTypeTemplateParm:
3773 return CXCursor_NonTypeTemplateParameter;
3774 case Decl::TemplateTemplateParm:
3775 return CXCursor_TemplateTemplateParameter;
3776 case Decl::FunctionTemplate:
3777 return CXCursor_FunctionTemplate;
3778 case Decl::ClassTemplate:
3779 return CXCursor_ClassTemplate;
3780 case Decl::AccessSpec:
3781 return CXCursor_CXXAccessSpecifier;
3782 case Decl::ClassTemplatePartialSpecialization:
3783 return CXCursor_ClassTemplatePartialSpecialization;
3784 case Decl::UsingDirective:
3785 return CXCursor_UsingDirective;
3786 case Decl::StaticAssert:
3787 return CXCursor_StaticAssert;
3788 case Decl::Friend:
3789 return CXCursor_FriendDecl;
3790 case Decl::TranslationUnit:
3791 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003792
Fangrui Song050229d2018-11-24 00:14:31 +00003793 case Decl::Using:
3794 case Decl::UnresolvedUsingValue:
3795 case Decl::UnresolvedUsingTypename:
3796 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003797
Fangrui Song050229d2018-11-24 00:14:31 +00003798 case Decl::ObjCPropertyImpl:
3799 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3800 case ObjCPropertyImplDecl::Dynamic:
3801 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003802
Fangrui Song050229d2018-11-24 00:14:31 +00003803 case ObjCPropertyImplDecl::Synthesize:
3804 return CXCursor_ObjCSynthesizeDecl;
3805 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003806 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003807
3808 case Decl::Import:
3809 return CXCursor_ModuleImportDecl;
3810
3811 case Decl::ObjCTypeParam:
3812 return CXCursor_TemplateTypeParameter;
3813
3814 default:
3815 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3816 switch (TD->getTagKind()) {
3817 case TTK_Interface: // fall through
3818 case TTK_Struct:
3819 return CXCursor_StructDecl;
3820 case TTK_Class:
3821 return CXCursor_ClassDecl;
3822 case TTK_Union:
3823 return CXCursor_UnionDecl;
3824 case TTK_Enum:
3825 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003826 }
Fangrui Song050229d2018-11-24 00:14:31 +00003827 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003828 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003829
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003830 return CXCursor_UnexposedDecl;
3831}
3832
Douglas Gregor55b037b2010-07-08 20:55:51 +00003833static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003834 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003835 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003836 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003837
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003838 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003839
Eric Liu88de9f62018-09-19 09:34:55 +00003840 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3841 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003842 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003843 auto MD = PP.getMacroDefinition(M->first);
3844 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003845 MacroInfo *MI = MD.getMacroInfo();
3846 if (MI && MI->isUsedForHeaderGuard())
3847 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003848
Eric Liud485df12018-09-05 14:59:17 +00003849 Results.AddResult(
3850 Result(M->first, MI,
3851 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3852 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003853 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003854 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003855
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003856 Results.ExitScope();
3857}
3858
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003859static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003860 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003861 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003862
Douglas Gregorce0e8562010-08-23 21:54:33 +00003863 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003864
Douglas Gregorce0e8562010-08-23 21:54:33 +00003865 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3866 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003867 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003868 Results.AddResult(Result("__func__", CCP_Constant));
3869 Results.ExitScope();
3870}
3871
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003872static void HandleCodeCompleteResults(Sema *S,
3873 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003874 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003875 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003876 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003877 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003878 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003879}
3880
Ilya Biryukov41109672018-12-13 15:36:32 +00003881static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003882mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003883 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003884 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003885 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003886
John McCallfaf5fb42010-08-26 23:41:50 +00003887 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003888 return CodeCompletionContext::CCC_ClassStructUnion;
3889
John McCallfaf5fb42010-08-26 23:41:50 +00003890 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003891 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003892
John McCallfaf5fb42010-08-26 23:41:50 +00003893 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003894 return CodeCompletionContext::CCC_ObjCImplementation;
3895
John McCallfaf5fb42010-08-26 23:41:50 +00003896 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003897 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003898
John McCallfaf5fb42010-08-26 23:41:50 +00003899 case Sema::PCC_Template:
3900 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003901 if (S.CurContext->isFileContext())
3902 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003903 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003904 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003905 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003906
John McCallfaf5fb42010-08-26 23:41:50 +00003907 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003908 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003909
John McCallfaf5fb42010-08-26 23:41:50 +00003910 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003911 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003912 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003913 return CodeCompletionContext::CCC_ParenthesizedExpression;
3914 else
3915 return CodeCompletionContext::CCC_Expression;
3916
3917 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003918 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003919 case Sema::PCC_Condition:
3920 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3921 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003922
John McCallfaf5fb42010-08-26 23:41:50 +00003923 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003924 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003925
John McCallfaf5fb42010-08-26 23:41:50 +00003926 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003927 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003928
3929 case Sema::PCC_ParenthesizedExpression:
3930 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003931
Douglas Gregor80039242011-02-15 20:33:25 +00003932 case Sema::PCC_LocalDeclarationSpecifiers:
3933 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003934 }
David Blaikie8a40f702012-01-17 06:56:22 +00003935
3936 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003937}
3938
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003939/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003940/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003941/// overridden function as well as adding new functionality.
3942///
3943/// \param S The semantic analysis object for which we are generating results.
3944///
3945/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003946/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003947static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3948 ResultBuilder &Results) {
3949 // Look through blocks.
3950 DeclContext *CurContext = S.CurContext;
3951 while (isa<BlockDecl>(CurContext))
3952 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003953
Douglas Gregorac322ec2010-08-27 21:18:54 +00003954 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3955 if (!Method || !Method->isVirtual())
3956 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003957
3958 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003959 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003960 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003961 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003962 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003963
Douglas Gregor75acd922011-09-27 23:30:47 +00003964 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003965 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003966 CodeCompletionBuilder Builder(Results.getAllocator(),
3967 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003968 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3969 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003970
Douglas Gregorac322ec2010-08-27 21:18:54 +00003971 // If we need a nested-name-specifier, add one now.
3972 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003973 NestedNameSpecifier *NNS = getRequiredQualification(
3974 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003975 if (NNS) {
3976 std::string Str;
3977 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003978 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003979 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003980 }
3981 } else if (!InContext->Equals(Overridden->getDeclContext()))
3982 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003983
Fangrui Song050229d2018-11-24 00:14:31 +00003984 Builder.AddTypedTextChunk(
3985 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003986 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003987 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003988 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003989 if (FirstParam)
3990 FirstParam = false;
3991 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003992 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003993
Aaron Ballman43b68be2014-03-07 17:50:17 +00003994 Builder.AddPlaceholderChunk(
3995 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003996 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003997 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003998 Results.AddResult(CodeCompletionResult(
3999 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
4000 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004001 Results.Ignore(Overridden);
4002 }
4003}
4004
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004005void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00004006 ModuleIdPath Path) {
4007 typedef CodeCompletionResult Result;
4008 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004009 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00004010 CodeCompletionContext::CCC_Other);
4011 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004012
Douglas Gregor07f43572012-01-29 18:15:03 +00004013 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004014 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00004015 typedef CodeCompletionResult Result;
4016 if (Path.empty()) {
4017 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00004018 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00004019 PP.getHeaderSearchInfo().collectAllModules(Modules);
4020 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
4021 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004022 Builder.getAllocator().CopyString(Modules[I]->Name));
4023 Results.AddResult(Result(
4024 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4025 Modules[I]->isAvailable() ? CXAvailability_Available
4026 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004027 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00004028 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00004029 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00004030 Module *Mod =
4031 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
4032 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00004033 // Enumerate submodules.
4034 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004035 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00004036 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00004037 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004038
Douglas Gregor07f43572012-01-29 18:15:03 +00004039 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00004040 Builder.getAllocator().CopyString((*Sub)->Name));
4041 Results.AddResult(Result(
4042 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
4043 (*Sub)->isAvailable() ? CXAvailability_Available
4044 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00004045 }
4046 }
4047 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004048 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00004049 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004050 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00004051}
4052
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004053void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004054 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004055 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004056 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004057 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00004058 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004059
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004060 // Determine how to filter results, e.g., so that the names of
4061 // values (functions, enumerators, function templates, etc.) are
4062 // only allowed where we can have an expression.
4063 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004064 case PCC_Namespace:
4065 case PCC_Class:
4066 case PCC_ObjCInterface:
4067 case PCC_ObjCImplementation:
4068 case PCC_ObjCInstanceVariableList:
4069 case PCC_Template:
4070 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004071 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004072 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004073 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4074 break;
4075
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004076 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00004077 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00004078 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004079 case PCC_ForInit:
4080 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00004081 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00004082 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4083 else
4084 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004085
David Blaikiebbafb8a2012-03-11 07:00:24 +00004086 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00004087 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004088 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004089
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004090 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00004091 // Unfiltered
4092 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00004093 }
4094
Douglas Gregor9be0ed42010-08-26 16:36:48 +00004095 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004096 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00004097 auto ThisType = getCurrentThisType();
4098 if (!ThisType.isNull())
Sam McCall3dea5272019-06-10 15:17:52 +00004099 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(),
4100 VK_LValue);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004101
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004102 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004103 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004104 CodeCompleter->includeGlobals(),
4105 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00004106
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004107 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00004108 Results.ExitScope();
4109
Douglas Gregorce0e8562010-08-23 21:54:33 +00004110 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00004111 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004112 case PCC_Expression:
4113 case PCC_Statement:
4114 case PCC_RecoveryInFunction:
4115 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004116 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004117 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004118
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004119 case PCC_Namespace:
4120 case PCC_Class:
4121 case PCC_ObjCInterface:
4122 case PCC_ObjCImplementation:
4123 case PCC_ObjCInstanceVariableList:
4124 case PCC_Template:
4125 case PCC_MemberTemplate:
4126 case PCC_ForInit:
4127 case PCC_Condition:
4128 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00004129 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00004130 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00004131 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004132
Douglas Gregor9eb77012009-11-07 00:00:49 +00004133 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004134 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004135
Douglas Gregor50832e02010-09-20 22:39:41 +00004136 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004137 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00004138}
4139
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004140static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004141 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004142 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00004143 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004144 ResultBuilder &Results);
4145
4146void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
4147 bool AllowNonIdentifiers,
4148 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00004149 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004150 ResultBuilder Results(
4151 *this, CodeCompleter->getAllocator(),
4152 CodeCompleter->getCodeCompletionTUInfo(),
4153 AllowNestedNameSpecifiers
4154 // FIXME: Try to separate codepath leading here to deduce whether we
4155 // need an existing symbol or a new one.
4156 ? CodeCompletionContext::CCC_SymbolOrNewName
4157 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004158 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004159
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004160 // Type qualifiers can come after names.
4161 Results.AddResult(Result("const"));
4162 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00004163 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004164 Results.AddResult(Result("restrict"));
4165
David Blaikiebbafb8a2012-03-11 07:00:24 +00004166 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004167 if (getLangOpts().CPlusPlus11 &&
4168 (DS.getTypeSpecType() == DeclSpec::TST_class ||
4169 DS.getTypeSpecType() == DeclSpec::TST_struct))
4170 Results.AddResult("final");
4171
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004172 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004173 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004174 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004175
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004176 // Add nested-name-specifiers.
4177 if (AllowNestedNameSpecifiers) {
4178 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004179 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004180 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4181 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004182 CodeCompleter->includeGlobals(),
4183 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00004184 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004185 }
4186 }
4187 Results.ExitScope();
4188
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004189 // If we're in a context where we might have an expression (rather than a
4190 // declaration), and what we've seen so far is an Objective-C type that could
4191 // be a receiver of a class message, this may be a class message send with
4192 // the initial opening bracket '[' missing. Add appropriate completions.
4193 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00004194 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004195 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004196 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
4197 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00004198 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004199 (S->getFlags() & Scope::DeclScope) != 0 &&
4200 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00004201 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
4202 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004203 ParsedType T = DS.getRepAsType();
4204 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00004205 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00004206 }
4207
Douglas Gregor56ccce02010-08-24 04:59:56 +00004208 // Note that we intentionally suppress macro results here, since we do not
4209 // encourage using macros to produce the names of entities.
4210
Fangrui Song050229d2018-11-24 00:14:31 +00004211 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00004212 Results.data(), Results.size());
4213}
4214
Douglas Gregor68762e72010-08-23 21:17:50 +00004215struct Sema::CodeCompleteExpressionData {
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004216 CodeCompleteExpressionData(QualType PreferredType = QualType(),
4217 bool IsParenthesized = false)
Fangrui Song050229d2018-11-24 00:14:31 +00004218 : PreferredType(PreferredType), IntegralConstantExpression(false),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004219 ObjCCollection(false), IsParenthesized(IsParenthesized) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004220
Douglas Gregor68762e72010-08-23 21:17:50 +00004221 QualType PreferredType;
4222 bool IntegralConstantExpression;
4223 bool ObjCCollection;
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004224 bool IsParenthesized;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004225 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00004226};
4227
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004228namespace {
4229/// Information that allows to avoid completing redundant enumerators.
4230struct CoveredEnumerators {
4231 llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen;
4232 NestedNameSpecifier *SuggestedQualifier = nullptr;
4233};
4234} // namespace
4235
4236static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
4237 EnumDecl *Enum, DeclContext *CurContext,
4238 const CoveredEnumerators &Enumerators) {
4239 NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
4240 if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
4241 // If there are no prior enumerators in C++, check whether we have to
4242 // qualify the names of the enumerators that we suggest, because they
4243 // may not be visible in this scope.
4244 Qualifier = getRequiredQualification(Context, CurContext, Enum);
4245 }
4246
4247 Results.EnterNewScope();
4248 for (auto *E : Enum->enumerators()) {
4249 if (Enumerators.Seen.count(E))
4250 continue;
4251
4252 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
4253 Results.AddResult(R, CurContext, nullptr, false);
4254 }
4255 Results.ExitScope();
4256}
4257
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004258/// Try to find a corresponding FunctionProtoType for function-like types (e.g.
4259/// function pointers, std::function, etc).
4260static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) {
4261 assert(!T.isNull());
4262 // Try to extract first template argument from std::function<> and similar.
4263 // Note we only handle the sugared types, they closely match what users wrote.
4264 // We explicitly choose to not handle ClassTemplateSpecializationDecl.
4265 if (auto *Specialization = T->getAs<TemplateSpecializationType>()) {
4266 if (Specialization->getNumArgs() != 1)
4267 return nullptr;
4268 const TemplateArgument &Argument = Specialization->getArg(0);
4269 if (Argument.getKind() != TemplateArgument::Type)
4270 return nullptr;
4271 return Argument.getAsType()->getAs<FunctionProtoType>();
4272 }
4273 // Handle other cases.
4274 if (T->isPointerType())
4275 T = T->getPointeeType();
4276 return T->getAs<FunctionProtoType>();
4277}
4278
4279/// Adds a pattern completion for a lambda expression with the specified
4280/// parameter types and placeholders for parameter names.
4281static void AddLambdaCompletion(ResultBuilder &Results,
4282 llvm::ArrayRef<QualType> Parameters,
4283 const LangOptions &LangOpts) {
Ilya Biryukovfd11a5f2019-05-23 16:39:26 +00004284 if (!Results.includeCodePatterns())
4285 return;
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004286 CodeCompletionBuilder Completion(Results.getAllocator(),
4287 Results.getCodeCompletionTUInfo());
4288 // [](<parameters>) {}
4289 Completion.AddChunk(CodeCompletionString::CK_LeftBracket);
4290 Completion.AddPlaceholderChunk("=");
4291 Completion.AddChunk(CodeCompletionString::CK_RightBracket);
4292 if (!Parameters.empty()) {
4293 Completion.AddChunk(CodeCompletionString::CK_LeftParen);
4294 bool First = true;
4295 for (auto Parameter : Parameters) {
4296 if (!First)
4297 Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma);
4298 else
4299 First = false;
4300
4301 constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!";
4302 std::string Type = NamePlaceholder;
4303 Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts));
4304 llvm::StringRef Prefix, Suffix;
4305 std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder);
4306 Prefix = Prefix.rtrim();
4307 Suffix = Suffix.ltrim();
4308
4309 Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix));
4310 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4311 Completion.AddPlaceholderChunk("parameter");
4312 Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix));
4313 };
4314 Completion.AddChunk(CodeCompletionString::CK_RightParen);
4315 }
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004316 Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004317 Completion.AddChunk(CodeCompletionString::CK_LeftBrace);
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004318 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004319 Completion.AddPlaceholderChunk("body");
Ilya Biryukov47fd4f02019-05-24 16:16:15 +00004320 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004321 Completion.AddChunk(CodeCompletionString::CK_RightBrace);
4322
4323 Results.AddResult(Completion.TakeString());
4324}
4325
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004326/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004327/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004328void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00004329 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00004330 ResultBuilder Results(
4331 *this, CodeCompleter->getAllocator(),
4332 CodeCompleter->getCodeCompletionTUInfo(),
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004333 CodeCompletionContext(
4334 Data.IsParenthesized
4335 ? CodeCompletionContext::CCC_ParenthesizedExpression
4336 : CodeCompletionContext::CCC_Expression,
4337 Data.PreferredType));
4338 auto PCC =
4339 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression;
Douglas Gregor68762e72010-08-23 21:17:50 +00004340 if (Data.ObjCCollection)
4341 Results.setFilter(&ResultBuilder::IsObjCCollection);
4342 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00004343 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004344 else if (WantTypesInContext(PCC, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004345 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4346 else
4347 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00004348
4349 if (!Data.PreferredType.isNull())
4350 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004351
Douglas Gregor68762e72010-08-23 21:17:50 +00004352 // Ignore any declarations that we were told that we don't care about.
4353 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
4354 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004355
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004356 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004357 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004358 CodeCompleter->includeGlobals(),
4359 CodeCompleter->loadExternal());
4360
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004361 Results.EnterNewScope();
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004362 AddOrdinaryNameResults(PCC, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004363 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004364
Douglas Gregor55b037b2010-07-08 20:55:51 +00004365 bool PreferredTypeIsPointer = false;
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004366 if (!Data.PreferredType.isNull()) {
Fangrui Song050229d2018-11-24 00:14:31 +00004367 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
4368 Data.PreferredType->isMemberPointerType() ||
4369 Data.PreferredType->isBlockPointerType();
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004370 if (Data.PreferredType->isEnumeralType()) {
4371 EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl();
4372 if (auto *Def = Enum->getDefinition())
4373 Enum = Def;
4374 // FIXME: collect covered enumerators in cases like:
4375 // if (x == my_enum::one) { ... } else if (x == ^) {}
4376 AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators());
4377 }
4378 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004379
Fangrui Song050229d2018-11-24 00:14:31 +00004380 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00004381 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00004382 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00004383
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004384 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004385 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
4386 PreferredTypeIsPointer);
Ilya Biryukov3a2f0e42019-05-23 07:45:35 +00004387
4388 // Complete a lambda expression when preferred type is a function.
4389 if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) {
4390 if (const FunctionProtoType *F =
4391 TryDeconstructFunctionLike(Data.PreferredType))
4392 AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts());
4393 }
4394
Eric Liuf5ba09f2018-07-04 10:01:18 +00004395 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4396 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004397}
4398
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004399void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType,
4400 bool IsParenthesized) {
4401 return CodeCompleteExpression(
4402 S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004403}
4404
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004405void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E,
4406 QualType PreferredType) {
Douglas Gregoreda7e542010-09-18 01:28:11 +00004407 if (E.isInvalid())
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004408 CodeCompleteExpression(S, PreferredType);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00004409 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00004410 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00004411}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004412
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004413/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00004414/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00004415typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00004416
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004417/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004418static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
4419 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
4420 if (Interface->hasDefinition())
4421 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004422
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004423 return Interface;
4424 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004425
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004426 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4427 if (Protocol->hasDefinition())
4428 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004429
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004430 return Protocol;
4431 }
4432 return Container;
4433}
4434
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004435/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00004436/// declaration \p BD.
4437static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
4438 CodeCompletionBuilder &Builder,
4439 const NamedDecl *BD,
4440 const FunctionTypeLoc &BlockLoc,
4441 const FunctionProtoTypeLoc &BlockProtoLoc) {
4442 Builder.AddResultTypeChunk(
4443 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
4444 Policy, Builder.getAllocator()));
4445
4446 AddTypedNameChunk(Context, Policy, BD, Builder);
4447 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4448
4449 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
4450 Builder.AddPlaceholderChunk("...");
4451 } else {
4452 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
4453 if (I)
4454 Builder.AddChunk(CodeCompletionString::CK_Comma);
4455
4456 // Format the placeholder string.
4457 std::string PlaceholderStr =
4458 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
4459
4460 if (I == N - 1 && BlockProtoLoc &&
4461 BlockProtoLoc.getTypePtr()->isVariadic())
4462 PlaceholderStr += ", ...";
4463
4464 // Add the placeholder string.
4465 Builder.AddPlaceholderChunk(
4466 Builder.getAllocator().CopyString(PlaceholderStr));
4467 }
4468 }
4469
4470 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4471}
4472
Fangrui Song050229d2018-11-24 00:14:31 +00004473static void
4474AddObjCProperties(const CodeCompletionContext &CCContext,
4475 ObjCContainerDecl *Container, bool AllowCategories,
4476 bool AllowNullaryMethods, DeclContext *CurContext,
4477 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
4478 bool IsBaseExprStatement = false,
4479 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004480 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004481
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004482 // Retrieve the definition.
4483 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004484
Douglas Gregor9291bad2009-11-18 01:29:26 +00004485 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004486 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004487 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004488 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004489
Alex Lorenzbaef8022016-11-09 13:43:18 +00004490 // FIXME: Provide block invocation completion for non-statement
4491 // expressions.
4492 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4493 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004494 Result R = Result(P, Results.getBasePriority(P), nullptr);
4495 if (!InOriginalClass)
4496 setInBaseClass(R);
4497 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004498 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004499 }
4500
4501 // Block setter and invocation completion is provided only when we are able
4502 // to find the FunctionProtoTypeLoc with parameter names for the block.
4503 FunctionTypeLoc BlockLoc;
4504 FunctionProtoTypeLoc BlockProtoLoc;
4505 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4506 BlockProtoLoc);
4507 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004508 Result R = Result(P, Results.getBasePriority(P), nullptr);
4509 if (!InOriginalClass)
4510 setInBaseClass(R);
4511 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004512 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004513 }
4514
4515 // The default completion result for block properties should be the block
4516 // invocation completion when the base expression is a statement.
4517 CodeCompletionBuilder Builder(Results.getAllocator(),
4518 Results.getCodeCompletionTUInfo());
4519 AddObjCBlockCall(Container->getASTContext(),
4520 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4521 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004522 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4523 if (!InOriginalClass)
4524 setInBaseClass(R);
4525 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004526
4527 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004528 // statement and the block property is mutable.
4529 if (!P->isReadOnly()) {
4530 CodeCompletionBuilder Builder(Results.getAllocator(),
4531 Results.getCodeCompletionTUInfo());
4532 AddResultTypeChunk(Container->getASTContext(),
4533 getCompletionPrintingPolicy(Results.getSema()), P,
4534 CCContext.getBaseType(), Builder);
4535 Builder.AddTypedTextChunk(
4536 Results.getAllocator().CopyString(P->getName()));
4537 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004538
Alex Lorenzbaef8022016-11-09 13:43:18 +00004539 std::string PlaceholderStr = formatBlockPlaceholder(
4540 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4541 BlockProtoLoc, /*SuppressBlockName=*/true);
4542 // Add the placeholder string.
4543 Builder.AddPlaceholderChunk(
4544 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004545
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004546 // When completing blocks properties that return void the default
4547 // property completion result should show up before the setter,
4548 // otherwise the setter completion should show up before the default
4549 // property completion, as we normally want to use the result of the
4550 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004551 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004552 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004553 Results.getBasePriority(P) +
4554 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4555 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004556 : -CCD_BlockPropertySetter));
4557 if (!InOriginalClass)
4558 setInBaseClass(R);
4559 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004560 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004561 };
4562
4563 if (IsClassProperty) {
4564 for (const auto *P : Container->class_properties())
4565 AddProperty(P);
4566 } else {
4567 for (const auto *P : Container->instance_properties())
4568 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004569 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004570
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004571 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004572 if (AllowNullaryMethods) {
4573 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004574 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004575 // Adds a method result
4576 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4577 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4578 if (!Name)
4579 return;
4580 if (!AddedProperties.insert(Name).second)
4581 return;
4582 CodeCompletionBuilder Builder(Results.getAllocator(),
4583 Results.getCodeCompletionTUInfo());
4584 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4585 Builder.AddTypedTextChunk(
4586 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004587 Result R = Result(Builder.TakeString(), M,
4588 CCP_MemberDeclaration + CCD_MethodAsProperty);
4589 if (!InOriginalClass)
4590 setInBaseClass(R);
4591 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004592 };
4593
4594 if (IsClassProperty) {
4595 for (const auto *M : Container->methods()) {
4596 // Gather the class method that can be used as implicit property
4597 // getters. Methods with arguments or methods that return void aren't
4598 // added to the results as they can't be used as a getter.
4599 if (!M->getSelector().isUnarySelector() ||
4600 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4601 continue;
4602 AddMethod(M);
4603 }
4604 } else {
4605 for (auto *M : Container->methods()) {
4606 if (M->getSelector().isUnarySelector())
4607 AddMethod(M);
4608 }
Douglas Gregor95147142011-05-05 15:50:42 +00004609 }
4610 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004611
Douglas Gregor9291bad2009-11-18 01:29:26 +00004612 // Add properties in referenced protocols.
4613 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004614 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004615 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004616 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004617 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004618 /*InOriginalClass*/ false);
4619 } else if (ObjCInterfaceDecl *IFace =
4620 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004621 if (AllowCategories) {
4622 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004623 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004624 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004625 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004626 IsBaseExprStatement, IsClassProperty,
4627 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004628 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004629
Douglas Gregor9291bad2009-11-18 01:29:26 +00004630 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004631 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004632 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004633 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004634 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004635 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004636
Douglas Gregor9291bad2009-11-18 01:29:26 +00004637 // Look in the superclass.
4638 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004639 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004640 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004641 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004642 /*InOriginalClass*/ false);
4643 } else if (const auto *Category =
4644 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004645 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004646 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004647 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004648 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004649 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004650 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004651 }
4652}
4653
Sam McCall3dea5272019-06-10 15:17:52 +00004654static void AddRecordMembersCompletionResults(
4655 Sema &SemaRef, ResultBuilder &Results, Scope *S, QualType BaseType,
4656 ExprValueKind BaseKind, RecordDecl *RD, Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004657 // Indicate that we are performing a member access, and the cv-qualifiers
4658 // for the base object type.
Sam McCall3dea5272019-06-10 15:17:52 +00004659 Results.setObjectTypeQualifiers(BaseType.getQualifiers(), BaseKind);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004660
4661 // Access to a C/C++ class, struct, or union.
4662 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004663 std::vector<FixItHint> FixIts;
4664 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004665 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004666 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004667 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004668 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004669 /*IncludeDependentBases=*/true,
4670 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004671
4672 if (SemaRef.getLangOpts().CPlusPlus) {
4673 if (!Results.empty()) {
4674 // The "template" keyword can follow "->" or "." in the grammar.
4675 // However, we only want to suggest the template keyword if something
4676 // is dependent.
4677 bool IsDependent = BaseType->isDependentType();
4678 if (!IsDependent) {
4679 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4680 if (DeclContext *Ctx = DepScope->getEntity()) {
4681 IsDependent = Ctx->isDependentContext();
4682 break;
4683 }
4684 }
4685
4686 if (IsDependent)
4687 Results.AddResult(CodeCompletionResult("template"));
4688 }
4689 }
4690}
4691
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004692void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004693 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004694 SourceLocation OpLoc, bool IsArrow,
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004695 bool IsBaseExprStatement,
4696 QualType PreferredType) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004697 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004698 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004699
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004700 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4701 if (ConvertedBase.isInvalid())
4702 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004703 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4704
4705 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004706
4707 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004708 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004709 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004710 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004711
Douglas Gregor21325842011-07-07 16:03:39 +00004712 if (IsArrow) {
4713 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004714 } else {
4715 if (ConvertedBaseType->isObjCObjectPointerType() ||
4716 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004717 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004718 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004719 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4720 }
4721 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004722
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004723 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Ilya Biryukov4f9543b2019-01-31 20:20:32 +00004724 CCContext.setPreferredType(PreferredType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004725 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004726 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004727 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004728
Fangrui Song050229d2018-11-24 00:14:31 +00004729 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4730 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004731 if (!Base)
4732 return false;
4733
4734 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4735 if (ConvertedBase.isInvalid())
4736 return false;
4737 Base = ConvertedBase.get();
4738
4739 QualType BaseType = Base->getType();
Sam McCall3dea5272019-06-10 15:17:52 +00004740 ExprValueKind BaseKind = Base->getValueKind();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004741
4742 if (IsArrow) {
Sam McCall3dea5272019-06-10 15:17:52 +00004743 if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004744 BaseType = Ptr->getPointeeType();
Sam McCall3dea5272019-06-10 15:17:52 +00004745 BaseKind = VK_LValue;
4746 } else if (BaseType->isObjCObjectPointerType())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004747 /*Do nothing*/;
4748 else
4749 return false;
4750 }
4751
4752 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Sam McCall3dea5272019-06-10 15:17:52 +00004753 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004754 Record->getDecl(),
4755 std::move(AccessOpFixIt));
4756 } else if (const auto *TST =
4757 BaseType->getAs<TemplateSpecializationType>()) {
4758 TemplateName TN = TST->getTemplateName();
4759 if (const auto *TD =
4760 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4761 CXXRecordDecl *RD = TD->getTemplatedDecl();
Sam McCall3dea5272019-06-10 15:17:52 +00004762 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
4763 RD, std::move(AccessOpFixIt));
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004764 }
4765 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4766 if (auto *RD = ICNT->getDecl())
Sam McCall3dea5272019-06-10 15:17:52 +00004767 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind,
4768 RD, std::move(AccessOpFixIt));
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004769 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4770 // Objective-C property reference.
4771 AddedPropertiesSet AddedProperties;
4772
4773 if (const ObjCObjectPointerType *ObjCPtr =
4774 BaseType->getAsObjCInterfacePointerType()) {
4775 // Add property results based on our interface.
4776 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4777 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4778 /*AllowNullaryMethods=*/true, CurContext,
4779 AddedProperties, Results, IsBaseExprStatement);
4780 }
4781
4782 // Add properties from the protocols in a qualified interface.
4783 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4784 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4785 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004786 IsBaseExprStatement, /*IsClassProperty*/ false,
4787 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004788 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4789 (!IsArrow && BaseType->isObjCObjectType())) {
4790 // Objective-C instance variable access.
4791 ObjCInterfaceDecl *Class = nullptr;
4792 if (const ObjCObjectPointerType *ObjCPtr =
4793 BaseType->getAs<ObjCObjectPointerType>())
4794 Class = ObjCPtr->getInterfaceDecl();
4795 else
4796 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4797
4798 // Add all ivars from this class and its superclasses.
4799 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004800 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004801 Results.setFilter(&ResultBuilder::IsObjCIvar);
4802 LookupVisibleDecls(
4803 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4804 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4805 }
4806 }
4807
4808 // FIXME: How do we cope with isa?
4809 return true;
4810 };
4811
Douglas Gregor9291bad2009-11-18 01:29:26 +00004812 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004813
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004814 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4815 if (CodeCompleter->includeFixIts()) {
4816 const CharSourceRange OpRange =
4817 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4818 CompletionSucceded |= DoCompletion(
4819 OtherOpBase, !IsArrow,
4820 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004821 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004822
Douglas Gregor9291bad2009-11-18 01:29:26 +00004823 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004824
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004825 if (!CompletionSucceded)
4826 return;
4827
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004828 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004829 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4830 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004831}
4832
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004833void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4834 IdentifierInfo &ClassName,
4835 SourceLocation ClassNameLoc,
4836 bool IsBaseExprStatement) {
4837 IdentifierInfo *ClassNamePtr = &ClassName;
4838 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4839 if (!IFace)
4840 return;
4841 CodeCompletionContext CCContext(
4842 CodeCompletionContext::CCC_ObjCPropertyAccess);
4843 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4844 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4845 &ResultBuilder::IsMember);
4846 Results.EnterNewScope();
4847 AddedPropertiesSet AddedProperties;
4848 AddObjCProperties(CCContext, IFace, true,
4849 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4850 Results, IsBaseExprStatement,
4851 /*IsClassProperty=*/true);
4852 Results.ExitScope();
4853 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4854 Results.data(), Results.size());
4855}
4856
Faisal Vali090da2d2018-01-01 18:23:28 +00004857void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004858 if (!CodeCompleter)
4859 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004860
4861 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004862 enum CodeCompletionContext::Kind ContextKind =
4863 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004864 switch ((DeclSpec::TST)TagSpec) {
4865 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004866 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004867 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004868 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004869
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004870 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004871 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004872 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004873 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004874
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004875 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004876 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004877 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004878 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004879 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
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 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004883 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004884 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004885
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004886 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4887 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004888 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004889
4890 // First pass: look for tags.
4891 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004892 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004893 CodeCompleter->includeGlobals(),
4894 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004895
Douglas Gregor39982192010-08-15 06:18:01 +00004896 if (CodeCompleter->includeGlobals()) {
4897 // Second pass: look for nested name specifiers.
4898 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004899 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4900 CodeCompleter->includeGlobals(),
4901 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004902 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004903
Douglas Gregor0ac41382010-09-23 23:01:17 +00004904 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004905 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004906}
4907
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004908static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4909 const LangOptions &LangOpts) {
4910 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4911 Results.AddResult("const");
4912 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4913 Results.AddResult("volatile");
4914 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4915 Results.AddResult("restrict");
4916 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4917 Results.AddResult("_Atomic");
4918 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4919 Results.AddResult("__unaligned");
4920}
4921
Douglas Gregor28c78432010-08-27 17:35:51 +00004922void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004923 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004924 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004925 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004926 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004927 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004928 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004929 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004930 Results.data(), Results.size());
4931}
4932
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004933void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4934 const VirtSpecifiers *VS) {
4935 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4936 CodeCompleter->getCodeCompletionTUInfo(),
4937 CodeCompletionContext::CCC_TypeQualifiers);
4938 Results.EnterNewScope();
4939 AddTypeQualifierResults(DS, Results, LangOpts);
4940 if (LangOpts.CPlusPlus11) {
4941 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004942 if (D.getContext() == DeclaratorContext::MemberContext &&
4943 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004944 if (!VS || !VS->isFinalSpecified())
4945 Results.AddResult("final");
4946 if (!VS || !VS->isOverrideSpecified())
4947 Results.AddResult("override");
4948 }
4949 }
4950 Results.ExitScope();
4951 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4952 Results.data(), Results.size());
4953}
4954
Benjamin Kramer72dae622016-02-18 15:30:24 +00004955void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4956 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4957}
4958
Douglas Gregord328d572009-09-21 18:10:23 +00004959void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004960 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004961 return;
John McCall5939b162011-08-06 07:30:58 +00004962
Richard Smithef6c43d2018-07-26 18:41:30 +00004963 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004964 // Condition expression might be invalid, do not continue in this case.
4965 if (!Switch->getCond())
4966 return;
John McCall5939b162011-08-06 07:30:58 +00004967 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4968 if (!type->isEnumeralType()) {
4969 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004970 Data.IntegralConstantExpression = true;
4971 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004972 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004973 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004974
Douglas Gregord328d572009-09-21 18:10:23 +00004975 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004976 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004977 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004978 if (EnumDecl *Def = Enum->getDefinition())
4979 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004980
Douglas Gregord328d572009-09-21 18:10:23 +00004981 // Determine which enumerators we have already seen in the switch statement.
4982 // FIXME: Ideally, we would also be able to look *past* the code-completion
4983 // token, in case we are code-completing in the middle of the switch and not
4984 // at the end. However, we aren't able to do so at the moment.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00004985 CoveredEnumerators Enumerators;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004986 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004987 SC = SC->getNextSwitchCase()) {
4988 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4989 if (!Case)
4990 continue;
4991
4992 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004993 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4994 if (auto *Enumerator =
4995 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004996 // We look into the AST of the case statement to determine which
4997 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004998 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004999 // values of each enumerator. However, value-based approach would not
5000 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00005001 // template are type- and value-dependent.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005002 Enumerators.Seen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005003
Douglas Gregorf2510672009-09-21 19:57:38 +00005004 // If this is a qualified-id, keep track of the nested-name-specifier
5005 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00005006 //
5007 // switch (TagD.getKind()) {
5008 // case TagDecl::TK_enum:
5009 // break;
5010 // case XXX
5011 //
Douglas Gregorf2510672009-09-21 19:57:38 +00005012 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00005013 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
5014 // TK_struct, and TK_class.
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005015 Enumerators.SuggestedQualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00005016 }
5017 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005018
Douglas Gregord328d572009-09-21 18:10:23 +00005019 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005020 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005021 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005022 CodeCompletionContext::CCC_Expression);
Ilya Biryukov600ec01b2019-05-16 16:06:57 +00005023 AddEnumerators(Results, Context, Enum, CurContext, Enumerators);
Douglas Gregor285560922010-04-06 20:02:15 +00005024
Douglas Gregor21325842011-07-07 16:03:39 +00005025 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00005026 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00005027 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00005028 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5029 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00005030}
5031
Robert Wilhelm16e94b92013-08-09 18:02:13 +00005032static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005033 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005034 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005035
5036 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005037 if (!Args[I])
5038 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005039
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00005040 return false;
5041}
5042
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005043typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
5044
Fangrui Song050229d2018-11-24 00:14:31 +00005045static void mergeCandidatesWithResults(
5046 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
5047 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Fangrui Song899d1392019-04-24 14:43:05 +00005048 // Sort the overload candidate set by placing the best overloads first.
5049 llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X,
5050 const OverloadCandidate &Y) {
5051 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
5052 CandidateSet.getKind());
5053 });
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005054
Fangrui Song899d1392019-04-24 14:43:05 +00005055 // Add the remaining viable overload candidates as code-completion results.
5056 for (OverloadCandidate &Candidate : CandidateSet) {
5057 if (Candidate.Function && Candidate.Function->isDeleted())
5058 continue;
5059 if (Candidate.Viable)
5060 Results.push_back(ResultCandidate(Candidate.Function));
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005061 }
5062}
5063
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005064/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005065/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00005066static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00005067 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005068
5069 // Given the overloads 'Candidates' for a function call matching all arguments
5070 // up to N, return the type of the Nth parameter if it is the same for all
5071 // overload candidates.
5072 QualType ParamType;
5073 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00005074 if (const auto *FType = Candidate.getFunctionType())
5075 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005076 if (N < Proto->getNumParams()) {
5077 if (ParamType.isNull())
5078 ParamType = Proto->getParamType(N);
5079 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00005080 ParamType.getNonReferenceType(),
5081 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005082 // Otherwise return a default-constructed QualType.
5083 return QualType();
5084 }
5085 }
5086
5087 return ParamType;
5088}
5089
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005090static QualType
5091ProduceSignatureHelp(Sema &SemaRef, Scope *S,
5092 MutableArrayRef<ResultCandidate> Candidates,
5093 unsigned CurrentArg, SourceLocation OpenParLoc) {
5094 if (Candidates.empty())
5095 return QualType();
5096 SemaRef.CodeCompleter->ProcessOverloadCandidates(
5097 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
5098 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005099}
5100
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005101QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
5102 ArrayRef<Expr *> Args,
5103 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00005104 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005105 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005106
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005107 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00005108 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005109 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
5110 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005111 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00005112 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005113
John McCall57500772009-12-16 12:17:52 +00005114 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00005115 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00005116 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00005117
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005118 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00005119
John McCall57500772009-12-16 12:17:52 +00005120 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005121 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00005122 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005123 /*PartialOverloading=*/true);
5124 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
5125 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
5126 if (UME->hasExplicitTemplateArgs()) {
5127 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
5128 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00005129 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00005130
5131 // Add the base as first argument (use a nullptr if the base is implicit).
5132 SmallVector<Expr *, 12> ArgExprs(
5133 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005134 ArgExprs.append(Args.begin(), Args.end());
5135 UnresolvedSet<8> Decls;
5136 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00005137 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005138 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005139 /*SuppressUserConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00005140 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005141 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005142 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00005143 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005144 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00005145 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005146 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005147 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00005148 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005149 !FD->getType()->getAs<FunctionProtoType>())
5150 Results.push_back(ResultCandidate(FD));
5151 else
5152 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
5153 Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005154 /*SuppressUserConversions=*/false,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005155 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005156
5157 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
5158 // If expression's type is CXXRecordDecl, it may overload the function
5159 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005160 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00005161 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00005162 DeclarationName OpName =
5163 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005164 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
5165 LookupQualifiedName(R, DC);
5166 R.suppressDiagnostics();
5167 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
5168 ArgExprs.append(Args.begin(), Args.end());
5169 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
5170 /*ExplicitArgs=*/nullptr,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005171 /*SuppressUserConversions=*/false,
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00005172 /*PartialOverloading=*/true);
5173 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005174 } else {
5175 // Lastly we check whether expression's type is function pointer or
5176 // function.
5177 QualType T = NakedFn->getType();
5178 if (!T->getPointeeType().isNull())
5179 T = T->getPointeeType();
5180
5181 if (auto FP = T->getAs<FunctionProtoType>()) {
5182 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00005183 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005184 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005185 Results.push_back(ResultCandidate(FP));
5186 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00005187 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00005188 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005189 }
Douglas Gregorcabea402009-09-22 15:41:20 +00005190 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005191 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005192 QualType ParamType =
5193 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
5194 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005195}
5196
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005197QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
5198 SourceLocation Loc,
5199 ArrayRef<Expr *> Args,
5200 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005201 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005202 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005203
5204 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00005205 CXXRecordDecl *RD =
5206 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005207 if (!RD)
5208 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00005209
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005210 // FIXME: Provide support for member initializers.
5211 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005212
5213 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
5214
Fangrui Song050229d2018-11-24 00:14:31 +00005215 for (NamedDecl *C : LookupConstructors(RD)) {
5216 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
5217 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
5218 CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005219 /*SuppressUserConversions=*/false,
Richard Smith76b90272019-05-09 03:59:21 +00005220 /*PartialOverloading=*/true,
5221 /*AllowExplicit*/ true);
Fangrui Song050229d2018-11-24 00:14:31 +00005222 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
5223 AddTemplateOverloadCandidate(
5224 FTD, DeclAccessPair::make(FTD, C->getAccess()),
5225 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005226 /*SuppressUserConversions=*/false,
Hans Wennborgd2b9fc82019-05-06 09:51:10 +00005227 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00005228 }
5229 }
5230
5231 SmallVector<ResultCandidate, 8> Results;
5232 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00005233 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00005234}
5235
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00005236QualType Sema::ProduceCtorInitMemberSignatureHelp(
5237 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
5238 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
5239 if (!CodeCompleter)
5240 return QualType();
5241
5242 CXXConstructorDecl *Constructor =
5243 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
5244 if (!Constructor)
5245 return QualType();
5246 // FIXME: Add support for Base class constructors as well.
5247 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
5248 Constructor->getParent(), SS, TemplateTypeTy, II))
5249 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
5250 MemberDecl->getLocation(), ArgExprs,
5251 OpenParLoc);
5252 return QualType();
5253}
5254
John McCall48871652010-08-21 09:40:31 +00005255void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
5256 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005257 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005258 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005259 return;
5260 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005261
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00005262 CodeCompleteExpressionData Data;
5263 Data.PreferredType = VD->getType();
5264 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
5265 Data.IgnoreDecls.push_back(VD);
5266
5267 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00005268}
5269
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005270void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005271 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005272 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005273 mapCodeCompletionContext(*this, PCC_Statement));
5274 Results.setFilter(&ResultBuilder::IsOrdinaryName);
5275 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005276
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005277 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5278 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005279 CodeCompleter->includeGlobals(),
5280 CodeCompleter->loadExternal());
5281
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005282 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005283
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005284 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005285 CodeCompletionBuilder Builder(Results.getAllocator(),
5286 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005287 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005288 if (Results.includeCodePatterns()) {
5289 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5290 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5291 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5292 Builder.AddPlaceholderChunk("statements");
5293 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5294 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5295 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005296 Results.AddResult(Builder.TakeString());
5297
5298 // "else if" block
Ilya Biryukov30977fc2019-06-04 09:26:08 +00005299 Builder.AddTypedTextChunk("else if");
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005300 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5301 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00005302 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005303 Builder.AddPlaceholderChunk("condition");
5304 else
5305 Builder.AddPlaceholderChunk("expression");
5306 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00005307 if (Results.includeCodePatterns()) {
5308 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5309 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5310 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5311 Builder.AddPlaceholderChunk("statements");
5312 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5313 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5314 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005315 Results.AddResult(Builder.TakeString());
5316
5317 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005318
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005319 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00005320 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005321
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005322 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005323 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005324
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005325 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00005326 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00005327}
5328
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00005329void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005330 bool EnteringContext, QualType BaseType,
5331 QualType PreferredType) {
Eric Liu06d34022017-12-12 11:35:46 +00005332 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00005333 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005334
Eric Liu06d34022017-12-12 11:35:46 +00005335 // We want to keep the scope specifier even if it's invalid (e.g. the scope
5336 // "a::b::" is not corresponding to any context/namespace in the AST), since
5337 // it can be useful for global code completion which have information about
5338 // contexts/symbols that are not in the AST.
5339 if (SS.isInvalid()) {
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005340 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType);
Eric Liu06d34022017-12-12 11:35:46 +00005341 CC.setCXXScopeSpecifier(SS);
Eric Liu206740e2019-02-21 11:22:58 +00005342 // As SS is invalid, we try to collect accessible contexts from the current
5343 // scope with a dummy lookup so that the completion consumer can try to
5344 // guess what the specified scope is.
5345 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
5346 CodeCompleter->getCodeCompletionTUInfo(), CC);
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005347 if (!PreferredType.isNull())
5348 DummyResults.setPreferredType(PreferredType);
Eric Liu206740e2019-02-21 11:22:58 +00005349 if (S->getEntity()) {
5350 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
5351 BaseType);
5352 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5353 /*IncludeGlobalScope=*/false,
5354 /*LoadExternal=*/false);
5355 }
5356 HandleCodeCompleteResults(this, CodeCompleter,
5357 DummyResults.getCompletionContext(), nullptr, 0);
Eric Liu06d34022017-12-12 11:35:46 +00005358 return;
5359 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00005360 // Always pretend to enter a context to ensure that a dependent type
5361 // resolves to a dependent record.
5362 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00005363 if (!Ctx)
5364 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00005365
5366 // Try to instantiate any non-dependent declaration contexts before
5367 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00005368 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00005369 return;
5370
Ilya Biryukovb1296fa2019-05-28 15:21:03 +00005371 ResultBuilder Results(
5372 *this, CodeCompleter->getAllocator(),
5373 CodeCompleter->getCodeCompletionTUInfo(),
5374 CodeCompletionContext(CodeCompletionContext::CCC_Symbol, PreferredType));
5375 if (!PreferredType.isNull())
5376 Results.setPreferredType(PreferredType);
Douglas Gregorac322ec2010-08-27 21:18:54 +00005377 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00005378
Douglas Gregor3545ff42009-09-21 16:56:56 +00005379 // The "template" keyword can follow "::" in the grammar, but only
5380 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00005381 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005382 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00005383 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005384
5385 // Add calls to overridden virtual functions, if there are any.
5386 //
5387 // FIXME: This isn't wonderful, because we don't know whether we're actually
5388 // in a context that permits expressions. This is a general issue with
5389 // qualified-id completions.
5390 if (!EnteringContext)
5391 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005392 Results.ExitScope();
5393
Eric Liufead6ae2017-12-13 10:26:49 +00005394 if (CodeCompleter->includeNamespaceLevelDecls() ||
5395 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005396 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005397 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5398 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005399 /*IncludeDependentBases=*/true,
5400 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005401 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005402
Eric Liu06d34022017-12-12 11:35:46 +00005403 auto CC = Results.getCompletionContext();
5404 CC.setCXXScopeSpecifier(SS);
5405
5406 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
5407 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005408}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005409
5410void Sema::CodeCompleteUsing(Scope *S) {
5411 if (!CodeCompleter)
5412 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005413
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005414 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005415 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005416 // This can be both a using alias or using
5417 // declaration, in the former we expect a new name and a
5418 // symbol in the latter case.
5419 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005420 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005421 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005422
Douglas Gregor3545ff42009-09-21 16:56:56 +00005423 // If we aren't in class scope, we could see the "namespace" keyword.
5424 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005425 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005426
5427 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005428 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005429 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005430 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005431 CodeCompleter->includeGlobals(),
5432 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005433 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005434
5435 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5436 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005437}
5438
5439void Sema::CodeCompleteUsingDirective(Scope *S) {
5440 if (!CodeCompleter)
5441 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005442
Douglas Gregor3545ff42009-09-21 16:56:56 +00005443 // After "using namespace", we expect to see a namespace name or namespace
5444 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005445 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005446 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005447 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005448 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005449 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005450 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005451 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005452 CodeCompleter->includeGlobals(),
5453 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005454 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005455 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5456 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005457}
5458
Fangrui Song050229d2018-11-24 00:14:31 +00005459void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005460 if (!CodeCompleter)
5461 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005462
Ted Kremenekc37877d2013-10-08 17:08:03 +00005463 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005464 if (!S->getParent())
5465 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005466
Fangrui Song050229d2018-11-24 00:14:31 +00005467 bool SuppressedGlobalResults =
5468 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005469
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005470 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005471 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005472 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005473 ? CodeCompletionContext::CCC_Namespace
5474 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005475 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005476
Douglas Gregor0ac41382010-09-23 23:01:17 +00005477 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005478 // We only want to see those namespaces that have already been defined
5479 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005480 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005481 // definition of each namespace.
5482 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005483 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005484 NS(Ctx->decls_begin()),
5485 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005486 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005487 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005488
5489 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005490 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005491 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005492 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005493 NS = OrigToLatest.begin(),
5494 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005495 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005496 Results.AddResult(
5497 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5498 nullptr),
5499 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005500 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005501 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005502
Fangrui Song050229d2018-11-24 00:14:31 +00005503 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5504 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005505}
5506
Fangrui Song050229d2018-11-24 00:14:31 +00005507void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005508 if (!CodeCompleter)
5509 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005510
Douglas Gregor3545ff42009-09-21 16:56:56 +00005511 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005512 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005513 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005514 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005515 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005516 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005517 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005518 CodeCompleter->includeGlobals(),
5519 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005520 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5521 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005522}
5523
Douglas Gregorc811ede2009-09-18 20:05:18 +00005524void Sema::CodeCompleteOperatorName(Scope *S) {
5525 if (!CodeCompleter)
5526 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005527
John McCall276321a2010-08-25 06:19:51 +00005528 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005529 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005530 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005531 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005532 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005533 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005534
Richard Smith7fa2b742019-06-14 20:01:51 +00005535 // Add the names of overloadable operators. Note that OO_Conditional is not
5536 // actually overloadable.
Fangrui Song050229d2018-11-24 00:14:31 +00005537#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
Richard Smith7fa2b742019-06-14 20:01:51 +00005538 if (OO_##Name != OO_Conditional) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005539 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005540#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005541
Douglas Gregor3545ff42009-09-21 16:56:56 +00005542 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005543 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005544 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005545 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005546 CodeCompleter->includeGlobals(),
5547 CodeCompleter->loadExternal());
5548
Douglas Gregor3545ff42009-09-21 16:56:56 +00005549 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005550 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005551 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005552
5553 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5554 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005555}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005556
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005557void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005558 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005559 if (!ConstructorD)
5560 return;
5561
5562 AdjustDeclIfTemplate(ConstructorD);
5563
Fangrui Song050229d2018-11-24 00:14:31 +00005564 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005565 if (!Constructor)
5566 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005567
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005568 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005569 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005570 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005571 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005572
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005573 // Fill in any already-initialized fields or base classes.
5574 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5575 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005576 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005577 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005578 InitializedBases.insert(Context.getCanonicalType(
5579 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005580 else
Fangrui Song050229d2018-11-24 00:14:31 +00005581 InitializedFields.insert(
5582 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005583 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005584
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005585 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005586 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005587 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005588 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005589
5590 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5591 CodeCompletionBuilder Builder(Results.getAllocator(),
5592 Results.getCodeCompletionTUInfo());
5593 Builder.AddTypedTextChunk(Name);
5594 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005595 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005596 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005597 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005598 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5599 Builder);
5600 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5601 return Builder.TakeString();
5602 };
5603 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5604 const NamedDecl *ND) {
5605 CodeCompletionBuilder Builder(Results.getAllocator(),
5606 Results.getCodeCompletionTUInfo());
5607 Builder.AddTypedTextChunk(Name);
5608 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5609 Builder.AddPlaceholderChunk(Type);
5610 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5611 if (ND) {
5612 auto CCR = CodeCompletionResult(
5613 Builder.TakeString(), ND,
5614 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5615 if (isa<FieldDecl>(ND))
5616 CCR.CursorKind = CXCursor_MemberRef;
5617 return Results.AddResult(CCR);
5618 }
5619 return Results.AddResult(CodeCompletionResult(
5620 Builder.TakeString(),
5621 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5622 };
5623 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5624 const char *Name, const FieldDecl *FD) {
5625 if (!RD)
5626 return AddDefaultCtorInit(Name,
5627 FD ? Results.getAllocator().CopyString(
5628 FD->getType().getAsString(Policy))
5629 : Name,
5630 FD);
5631 auto Ctors = getConstructors(Context, RD);
5632 if (Ctors.begin() == Ctors.end())
5633 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005634 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005635 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5636 CCR.CursorKind = getCursorKindForDecl(Ctor);
5637 Results.AddResult(CCR);
5638 }
5639 };
5640 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5641 const char *BaseName =
5642 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5643 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5644 AddCtorsWithName(
5645 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5646 BaseName, nullptr);
5647 };
5648 auto AddField = [&](const FieldDecl *FD) {
5649 const char *FieldName =
5650 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5651 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5652 AddCtorsWithName(
5653 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5654 FieldName, FD);
5655 };
5656
Aaron Ballman574705e2014-03-13 15:41:46 +00005657 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005658 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5659 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005660 SawLastInitializer =
5661 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5662 Context.hasSameUnqualifiedType(
5663 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005664 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005665 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005666
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005667 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005668 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005669 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005670
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005671 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005672 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005673 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5674 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005675 SawLastInitializer =
5676 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5677 Context.hasSameUnqualifiedType(
5678 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005679 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005680 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005681
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005682 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005683 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005684 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005685
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005686 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005687 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005688 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5689 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005690 SawLastInitializer = !Initializers.empty() &&
5691 Initializers.back()->isAnyMemberInitializer() &&
5692 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005693 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005694 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005695
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005696 if (!Field->getDeclName())
5697 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005698
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005699 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005700 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005701 }
5702 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005703
Douglas Gregor0ac41382010-09-23 23:01:17 +00005704 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005705 Results.data(), Results.size());
5706}
5707
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005708/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005709static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005710 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005711 if (!DC)
5712 return false;
5713
5714 return DC->isFileContext();
5715}
5716
5717void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5718 bool AfterAmpersand) {
5719 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005720 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005721 CodeCompletionContext::CCC_Other);
5722 Results.EnterNewScope();
5723
5724 // Note what has already been captured.
5725 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5726 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005727 for (const auto &C : Intro.Captures) {
5728 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005729 IncludedThis = true;
5730 continue;
5731 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005732
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005733 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005734 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005735
Douglas Gregord8c61782012-02-15 15:34:24 +00005736 // Look for other capturable variables.
5737 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005738 for (const auto *D : S->decls()) {
5739 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005740 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005741 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005742
David Blaikie82e95a32014-11-19 07:49:47 +00005743 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005744 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005745 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005746 }
5747 }
5748
5749 // Add 'this', if it would be valid.
5750 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5751 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005752
Douglas Gregord8c61782012-02-15 15:34:24 +00005753 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005754
Douglas Gregord8c61782012-02-15 15:34:24 +00005755 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5756 Results.data(), Results.size());
5757}
5758
James Dennett596e4752012-06-14 03:11:41 +00005759/// Macro that optionally prepends an "@" to the string literal passed in via
5760/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005761#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005762
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005763static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005764 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005765 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005766 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005767 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005768
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005769 CodeCompletionBuilder Builder(Results.getAllocator(),
5770 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005771 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005772 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005773 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005774 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5775 Builder.AddPlaceholderChunk("property");
5776 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005777
Douglas Gregorf1934162010-01-13 21:24:21 +00005778 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005779 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
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}
5785
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005786static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005787 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005788 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005789
Douglas Gregorf1934162010-01-13 21:24:21 +00005790 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005791 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005792
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005793 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005794 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005795 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005796
Douglas Gregorf1934162010-01-13 21:24:21 +00005797 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005798 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005799
Douglas Gregorf1934162010-01-13 21:24:21 +00005800 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005801 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005802 }
5803}
5804
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005805static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005806 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005807 CodeCompletionBuilder Builder(Results.getAllocator(),
5808 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005809
Douglas Gregorf1934162010-01-13 21:24:21 +00005810 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005811 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005812 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5813 Builder.AddPlaceholderChunk("name");
5814 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005815
Douglas Gregorf4c33342010-05-28 00:22:41 +00005816 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005817 // @interface name
5818 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005819 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005820 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005821 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5822 Builder.AddPlaceholderChunk("class");
5823 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005824
Douglas Gregorf4c33342010-05-28 00:22:41 +00005825 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005826 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005827 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5828 Builder.AddPlaceholderChunk("protocol");
5829 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005830
Douglas Gregorf4c33342010-05-28 00:22:41 +00005831 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005832 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005833 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5834 Builder.AddPlaceholderChunk("class");
5835 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005836 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005837
Douglas Gregorf1934162010-01-13 21:24:21 +00005838 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005839 Builder.AddTypedTextChunk(
5840 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005841 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5842 Builder.AddPlaceholderChunk("alias");
5843 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5844 Builder.AddPlaceholderChunk("class");
5845 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005846
5847 if (Results.getSema().getLangOpts().Modules) {
5848 // @import name
5849 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5850 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5851 Builder.AddPlaceholderChunk("module");
5852 Results.AddResult(Result(Builder.TakeString()));
5853 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005854}
5855
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005856void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005857 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005858 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005859 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005860 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005861 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005862 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005863 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005864 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005865 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005866 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005867 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005868 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5869 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005870}
5871
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005872static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005873 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005874 CodeCompletionBuilder Builder(Results.getAllocator(),
5875 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005876
5877 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005878 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005879 if (Results.getSema().getLangOpts().CPlusPlus ||
5880 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005881 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005882 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005883 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005884 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5885 Builder.AddPlaceholderChunk("type-name");
5886 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5887 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005888
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005889 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005890 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005891 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005892 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5893 Builder.AddPlaceholderChunk("protocol-name");
5894 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5895 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005896
5897 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005898 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005899 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005900 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5901 Builder.AddPlaceholderChunk("selector");
5902 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5903 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005904
5905 // @"string"
5906 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005907 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005908 Builder.AddPlaceholderChunk("string");
5909 Builder.AddTextChunk("\"");
5910 Results.AddResult(Result(Builder.TakeString()));
5911
Douglas Gregor951de302012-07-17 23:24:47 +00005912 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005913 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005914 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005915 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005916 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5917 Results.AddResult(Result(Builder.TakeString()));
5918
Douglas Gregor951de302012-07-17 23:24:47 +00005919 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005920 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005921 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005922 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005923 Builder.AddChunk(CodeCompletionString::CK_Colon);
5924 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5925 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005926 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5927 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005928
Douglas Gregor951de302012-07-17 23:24:47 +00005929 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005930 Builder.AddResultTypeChunk("id");
5931 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005932 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005933 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5934 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005935}
5936
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005937static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005938 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005939 CodeCompletionBuilder Builder(Results.getAllocator(),
5940 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005941
Douglas Gregorf4c33342010-05-28 00:22:41 +00005942 if (Results.includeCodePatterns()) {
5943 // @try { statements } @catch ( declaration ) { statements } @finally
5944 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005945 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005946 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5947 Builder.AddPlaceholderChunk("statements");
5948 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5949 Builder.AddTextChunk("@catch");
5950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5951 Builder.AddPlaceholderChunk("parameter");
5952 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5953 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5954 Builder.AddPlaceholderChunk("statements");
5955 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5956 Builder.AddTextChunk("@finally");
5957 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5958 Builder.AddPlaceholderChunk("statements");
5959 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5960 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005961 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005962
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005963 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005964 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005965 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5966 Builder.AddPlaceholderChunk("expression");
5967 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005968
Douglas Gregorf4c33342010-05-28 00:22:41 +00005969 if (Results.includeCodePatterns()) {
5970 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005971 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005972 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5973 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5974 Builder.AddPlaceholderChunk("expression");
5975 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5976 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5977 Builder.AddPlaceholderChunk("statements");
5978 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005980 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005981}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005982
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005983static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005984 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005985 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005986 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5987 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5988 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005989 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005990 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005991}
5992
5993void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005995 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005996 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005997 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005998 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005999 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006000 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6001 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00006002}
6003
6004void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006005 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006006 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006007 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00006008 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006009 AddObjCStatementResults(Results, false);
6010 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006011 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006012 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6013 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006014}
6015
6016void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006017 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006018 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006019 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006020 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00006021 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006022 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006023 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6024 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00006025}
6026
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006027/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00006028/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00006029static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00006030 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00006031 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00006032 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006033
Bill Wendling44426052012-12-20 19:22:21 +00006034 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006035
Douglas Gregore6078da2009-11-19 00:14:45 +00006036 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00006037 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
6038 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00006039 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006040
Jordan Rose53cb2f32012-08-20 20:01:13 +00006041 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00006042 unsigned AssignCopyRetMask =
6043 Attributes &
6044 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
6045 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
6046 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
6047 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00006048 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00006049 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00006050 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00006051 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
6052 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00006053 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006054
Douglas Gregore6078da2009-11-19 00:14:45 +00006055 return false;
6056}
6057
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006058void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00006059 if (!CodeCompleter)
6060 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006061
Bill Wendling44426052012-12-20 19:22:21 +00006062 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006063
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006064 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006065 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006066 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00006067 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00006068 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00006069 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00006070 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00006071 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00006072 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00006073 ObjCDeclSpec::DQ_PR_unsafe_unretained))
6074 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00006075 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00006076 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00006077 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00006078 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00006079 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00006080 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00006081 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00006082 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00006083 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00006084 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00006085 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00006086 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00006087
6088 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00006089 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00006090 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00006091 Results.AddResult(CodeCompletionResult("weak"));
6092
Bill Wendling44426052012-12-20 19:22:21 +00006093 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006094 CodeCompletionBuilder Setter(Results.getAllocator(),
6095 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006096 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006097 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006098 Setter.AddPlaceholderChunk("method");
6099 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006100 }
Bill Wendling44426052012-12-20 19:22:21 +00006101 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006102 CodeCompletionBuilder Getter(Results.getAllocator(),
6103 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006104 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00006105 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006106 Getter.AddPlaceholderChunk("method");
6107 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00006108 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006109 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
6110 Results.AddResult(CodeCompletionResult("nonnull"));
6111 Results.AddResult(CodeCompletionResult("nullable"));
6112 Results.AddResult(CodeCompletionResult("null_unspecified"));
6113 Results.AddResult(CodeCompletionResult("null_resettable"));
6114 }
Steve Naroff936354c2009-10-08 21:55:05 +00006115 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006116 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6117 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00006118}
Steve Naroffeae65032009-11-07 02:08:14 +00006119
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006120/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00006121/// via code completion.
6122enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00006123 MK_Any, ///< Any kind of method, provided it means other specified criteria.
6124 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00006125 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006126};
6127
Fangrui Song050229d2018-11-24 00:14:31 +00006128static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006129 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006130 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006131 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006132 if (NumSelIdents > Sel.getNumArgs())
6133 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006134
Douglas Gregor67c692c2010-08-26 15:07:07 +00006135 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00006136 case MK_Any:
6137 break;
6138 case MK_ZeroArgSelector:
6139 return Sel.isUnarySelector();
6140 case MK_OneArgSelector:
6141 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006142 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006143
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006144 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
6145 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006146
Douglas Gregor67c692c2010-08-26 15:07:07 +00006147 for (unsigned I = 0; I != NumSelIdents; ++I)
6148 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
6149 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006150
Douglas Gregor67c692c2010-08-26 15:07:07 +00006151 return true;
6152}
6153
Douglas Gregorc8537c52009-11-19 07:41:15 +00006154static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
6155 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006156 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006157 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006158 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006159 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006160}
Douglas Gregor1154e272010-09-16 16:06:31 +00006161
Fangrui Song050229d2018-11-24 00:14:31 +00006162/// A set of selectors, which is used to avoid introducing multiple
6163/// completions with the same selector into the result set.
6164typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00006165
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006166/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006167/// container to the set of results.
6168///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006169/// The container will be a class, protocol, category, or implementation of
6170/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006171/// the superclasses of classes along with their categories, protocols, and
6172/// implementations.
6173///
6174/// \param Container the container in which we'll look to find methods.
6175///
James Dennett596e4752012-06-14 03:11:41 +00006176/// \param WantInstanceMethods Whether to add instance methods (only); if
6177/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006178///
6179/// \param CurContext the context in which we're performing the lookup that
6180/// finds methods.
6181///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006182/// \param AllowSameLength Whether we allow a method to be added to the list
6183/// when it has the same number of parameters as we have selector identifiers.
6184///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006185/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006186static void AddObjCMethods(ObjCContainerDecl *Container,
6187 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006188 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006189 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006190 VisitedSelectorSet &Selectors, bool AllowSameLength,
6191 ResultBuilder &Results, bool InOriginalClass = true,
6192 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00006193 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006194 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00006195 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00006196 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00006197 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00006198 // The instance methods on the root class can be messaged via the
6199 // metaclass.
6200 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00006201 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006202 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00006203 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006204 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00006205 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00006206
David Blaikie82e95a32014-11-19 07:49:47 +00006207 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006208 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006209
6210 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006211 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00006212 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00006213 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00006214 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00006215 Results.MaybeAddResult(R, CurContext);
6216 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006217 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006218
Douglas Gregorf37c9492010-09-16 15:34:59 +00006219 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006220 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00006221 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006222 const ObjCList<ObjCProtocolDecl> &Protocols =
6223 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006224 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006225 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00006226 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006227 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6228 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00006229 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00006230 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006231
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006232 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006233 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006234
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006235 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00006236 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006237 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6238 Selectors, AllowSameLength, Results, false, IsRootClass);
6239
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006240 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00006241 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006242 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00006243 CurContext, Selectors, AllowSameLength, Results,
6244 InOriginalClass, IsRootClass);
6245
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006246 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00006247 const ObjCList<ObjCProtocolDecl> &Protocols =
6248 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006249 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6250 E = Protocols.end();
6251 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00006252 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
6253 Selectors, AllowSameLength, Results, false, IsRootClass);
6254
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006255 // Add methods in category implementations.
6256 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006257 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6258 Selectors, AllowSameLength, Results, InOriginalClass,
6259 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006260 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006261
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006262 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00006263 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006264 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006265 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
6266 SelIdents, CurContext, Selectors, AllowSameLength, Results,
6267 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006268
6269 // Add methods in our implementation, if any.
6270 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00006271 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
6272 Selectors, AllowSameLength, Results, InOriginalClass,
6273 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006274}
6275
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006276void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006277 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006278 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006279 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006280 if (ObjCCategoryDecl *Category =
6281 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006282 Class = Category->getClassInterface();
6283
6284 if (!Class)
6285 return;
6286 }
6287
6288 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006289 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006290 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006291 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006292 Results.EnterNewScope();
6293
Douglas Gregor1154e272010-09-16 16:06:31 +00006294 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006295 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006296 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006297 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006298 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6299 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00006300}
6301
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006302void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00006303 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00006304 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006305 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00006306 if (ObjCCategoryDecl *Category =
6307 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00006308 Class = Category->getClassInterface();
6309
6310 if (!Class)
6311 return;
6312 }
6313
6314 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006315 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006316 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006317 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006318 Results.EnterNewScope();
6319
Douglas Gregor1154e272010-09-16 16:06:31 +00006320 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00006321 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
6322 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00006323
6324 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006325 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6326 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006327}
6328
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006329void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
6330 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006331 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006332 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006333 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006334 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006335
Douglas Gregor99fa2642010-08-24 01:06:58 +00006336 // Add context-sensitive, Objective-C parameter-passing keywords.
6337 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006338 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006339 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
6340 Results.AddResult("in");
6341 Results.AddResult("inout");
6342 AddedInOut = true;
6343 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006344 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006345 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
6346 Results.AddResult("out");
6347 if (!AddedInOut)
6348 Results.AddResult("inout");
6349 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006350 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00006351 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
6352 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00006353 Results.AddResult("bycopy");
6354 Results.AddResult("byref");
6355 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00006356 }
Douglas Gregor86b42682015-06-19 18:27:52 +00006357 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
6358 Results.AddResult("nonnull");
6359 Results.AddResult("nullable");
6360 Results.AddResult("null_unspecified");
6361 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006362
6363 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006364 // identifier IBAction refers to a macro, provide a completion item for
6365 // an action, e.g.,
6366 // IBAction)<#selector#>:(id)sender
6367 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00006368 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006369 CodeCompletionBuilder Builder(Results.getAllocator(),
6370 Results.getCodeCompletionTUInfo(),
6371 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006372 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006373 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006374 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006375 Builder.AddChunk(CodeCompletionString::CK_Colon);
6376 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006377 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00006378 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00006379 Builder.AddTextChunk("sender");
6380 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
6381 }
Douglas Gregored1f5972013-01-30 07:11:43 +00006382
6383 // If we're completing the return type, provide 'instancetype'.
6384 if (!IsParameter) {
6385 Results.AddResult(CodeCompletionResult("instancetype"));
6386 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006387
Douglas Gregor99fa2642010-08-24 01:06:58 +00006388 // Add various builtin type names and specifiers.
6389 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6390 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006391
Douglas Gregor99fa2642010-08-24 01:06:58 +00006392 // Add the various type names
6393 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6394 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6395 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006396 CodeCompleter->includeGlobals(),
6397 CodeCompleter->loadExternal());
6398
Douglas Gregor99fa2642010-08-24 01:06:58 +00006399 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006400 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006401
Eric Liuf5ba09f2018-07-04 10:01:18 +00006402 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006403 Results.data(), Results.size());
6404}
6405
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006406/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006407/// that it has some more-specific class type based on knowledge of
6408/// common uses of Objective-C. This routine returns that class type,
6409/// or NULL if no better result could be determined.
6410static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006411 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006412 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006413 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006414
6415 Selector Sel = Msg->getSelector();
6416 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006417 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006418
6419 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6420 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006421 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006422
6423 ObjCMethodDecl *Method = Msg->getMethodDecl();
6424 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006425 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006426
6427 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006428 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006429 switch (Msg->getReceiverKind()) {
6430 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006431 if (const ObjCObjectType *ObjType =
6432 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006433 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006434 break;
6435
6436 case ObjCMessageExpr::Instance: {
6437 QualType T = Msg->getInstanceReceiver()->getType();
6438 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6439 IFace = Ptr->getInterfaceDecl();
6440 break;
6441 }
6442
6443 case ObjCMessageExpr::SuperInstance:
6444 case ObjCMessageExpr::SuperClass:
6445 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006446 }
6447
6448 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006449 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006450
6451 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6452 if (Method->isInstanceMethod())
6453 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006454 .Case("retain", IFace)
6455 .Case("strong", IFace)
6456 .Case("autorelease", IFace)
6457 .Case("copy", IFace)
6458 .Case("copyWithZone", IFace)
6459 .Case("mutableCopy", IFace)
6460 .Case("mutableCopyWithZone", IFace)
6461 .Case("awakeFromCoder", IFace)
6462 .Case("replacementObjectFromCoder", IFace)
6463 .Case("class", IFace)
6464 .Case("classForCoder", IFace)
6465 .Case("superclass", Super)
6466 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006467
6468 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006469 .Case("new", IFace)
6470 .Case("alloc", IFace)
6471 .Case("allocWithZone", IFace)
6472 .Case("class", IFace)
6473 .Case("superclass", Super)
6474 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006475}
6476
Douglas Gregor6fc04132010-08-27 15:10:57 +00006477// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006478// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006479// function.
6480///
6481/// \param S The semantic analysis object.
6482///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006483/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006484/// the "super" keyword. Otherwise, we just need to provide the arguments.
6485///
6486/// \param SelIdents The identifiers in the selector that have already been
6487/// provided as arguments for a send to "super".
6488///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006489/// \param Results The set of results to augment.
6490///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006491/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006492/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006493static ObjCMethodDecl *
6494AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6495 ArrayRef<IdentifierInfo *> SelIdents,
6496 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006497 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6498 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006499 return nullptr;
6500
Douglas Gregor6fc04132010-08-27 15:10:57 +00006501 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6502 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006503 return nullptr;
6504
Douglas Gregor6fc04132010-08-27 15:10:57 +00006505 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006506 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006507 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6508 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006509 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006510 CurMethod->isInstanceMethod());
6511
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006512 // Check in categories or class extensions.
6513 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006514 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006515 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006516 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006517 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006518 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006519 }
6520 }
6521
Douglas Gregor6fc04132010-08-27 15:10:57 +00006522 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006523 return nullptr;
6524
Douglas Gregor6fc04132010-08-27 15:10:57 +00006525 // Check whether the superclass method has the same signature.
6526 if (CurMethod->param_size() != SuperMethod->param_size() ||
6527 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006528 return nullptr;
6529
Douglas Gregor6fc04132010-08-27 15:10:57 +00006530 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006531 CurPEnd = CurMethod->param_end(),
6532 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006533 CurP != CurPEnd; ++CurP, ++SuperP) {
6534 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006535 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006536 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006537 return nullptr;
6538
Douglas Gregor6fc04132010-08-27 15:10:57 +00006539 // Make sure we have a parameter name to forward!
6540 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006541 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006542 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006543
Douglas Gregor6fc04132010-08-27 15:10:57 +00006544 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006545 CodeCompletionBuilder Builder(Results.getAllocator(),
6546 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006547
Douglas Gregor6fc04132010-08-27 15:10:57 +00006548 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006549 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006550 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006551
6552 // If we need the "super" keyword, add it (plus some spacing).
6553 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006554 Builder.AddTypedTextChunk("super");
6555 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006556 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006557
Douglas Gregor6fc04132010-08-27 15:10:57 +00006558 Selector Sel = CurMethod->getSelector();
6559 if (Sel.isUnarySelector()) {
6560 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006561 Builder.AddTextChunk(
6562 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006563 else
Fangrui Song050229d2018-11-24 00:14:31 +00006564 Builder.AddTypedTextChunk(
6565 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006566 } else {
6567 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6568 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006569 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006570 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006571
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006572 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006573 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006574 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006575 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006576 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006577 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006578 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006579 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006580 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006581 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006582 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006583 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006584 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006585 }
6586 }
6587 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006588
Douglas Gregor78254c82012-03-27 23:34:16 +00006589 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6590 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006591 return SuperMethod;
6592}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006593
Douglas Gregora817a192010-05-27 23:06:34 +00006594void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006595 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006596 ResultBuilder Results(
6597 *this, CodeCompleter->getAllocator(),
6598 CodeCompleter->getCodeCompletionTUInfo(),
6599 CodeCompletionContext::CCC_ObjCMessageReceiver,
6600 getLangOpts().CPlusPlus11
6601 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6602 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006603
Douglas Gregora817a192010-05-27 23:06:34 +00006604 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6605 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006606 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006607 CodeCompleter->includeGlobals(),
6608 CodeCompleter->loadExternal());
6609
Douglas Gregora817a192010-05-27 23:06:34 +00006610 // If we are in an Objective-C method inside a class that has a superclass,
6611 // add "super" as an option.
6612 if (ObjCMethodDecl *Method = getCurMethodDecl())
6613 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006614 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006615 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006616
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006617 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006618 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006619
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006620 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006621 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006622
Douglas Gregora817a192010-05-27 23:06:34 +00006623 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006624
Douglas Gregora817a192010-05-27 23:06:34 +00006625 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006626 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006627 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006628 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006629}
6630
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006631void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006632 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006633 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006634 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006635 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6636 // Figure out which interface we're in.
6637 CDecl = CurMethod->getClassInterface();
6638 if (!CDecl)
6639 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006640
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006641 // Find the superclass of this class.
6642 CDecl = CDecl->getSuperClass();
6643 if (!CDecl)
6644 return;
6645
6646 if (CurMethod->isInstanceMethod()) {
6647 // We are inside an instance method, which means that the message
6648 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006649 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006650 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006651 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006652 }
6653
6654 // Fall through to send to the superclass in CDecl.
6655 } else {
6656 // "super" may be the name of a type or variable. Figure out which
6657 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006658 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006659 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006660 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6661 // "super" names an interface. Use it.
6662 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006663 if (const ObjCObjectType *Iface =
6664 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006665 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006666 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6667 // "super" names an unresolved type; we can't be more specific.
6668 } else {
6669 // Assume that "super" names some kind of value and parse that way.
6670 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006671 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006672 UnqualifiedId id;
6673 id.setIdentifier(Super, SuperLoc);
Bruno Ricci70ad3962019-03-25 17:08:51 +00006674 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
6675 /*HasTrailingLParen=*/false,
6676 /*IsAddressOfOperand=*/false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006677 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006678 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006679 }
6680
6681 // Fall through
6682 }
6683
John McCallba7bf592010-08-24 05:47:05 +00006684 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006685 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006686 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006687 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006688 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006689 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006690}
6691
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006692/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006693/// send, determine the preferred type (if any) for that argument expression.
6694static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6695 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006696 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006697 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006698
Douglas Gregor74661272010-09-21 00:03:25 +00006699 QualType PreferredType;
6700 unsigned BestPriority = CCP_Unlikely * 2;
6701 Result *ResultsData = Results.data();
6702 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6703 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006704 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006705 isa<ObjCMethodDecl>(R.Declaration)) {
6706 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006707 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006708 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006709 QualType MyPreferredType =
6710 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006711 if (R.Priority < BestPriority || PreferredType.isNull()) {
6712 BestPriority = R.Priority;
6713 PreferredType = MyPreferredType;
6714 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6715 MyPreferredType)) {
6716 PreferredType = QualType();
6717 }
6718 }
6719 }
6720 }
6721 }
6722
6723 return PreferredType;
6724}
6725
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006726static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006727 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006728 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006729 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006730 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006731 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006732 ObjCInterfaceDecl *CDecl = nullptr;
6733
Douglas Gregor8ce33212009-11-17 17:59:40 +00006734 // If the given name refers to an interface type, retrieve the
6735 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006736 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006737 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006738 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006739 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6740 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006741 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006742
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006743 // Add all of the factory methods in this Objective-C class, its protocols,
6744 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006745 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006746
6747 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006748 // completion.
6749 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006750 if (ObjCMethodDecl *SuperMethod =
6751 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006752 Results.Ignore(SuperMethod);
6753 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006754
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006755 // If we're inside an Objective-C method definition, prefer its selector to
6756 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006757 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006758 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006759
Douglas Gregor1154e272010-09-16 16:06:31 +00006760 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006761 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006762 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6763 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006764 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006765 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006766
Douglas Gregord720daf2010-04-06 17:30:22 +00006767 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006768 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006769 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006770 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006771 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006772 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006773 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006774 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006775 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006776
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006777 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006778 }
6779 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006780
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006781 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006782 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006783 M != MEnd; ++M) {
6784 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006785 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006786 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006787 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006788
Nico Weber2e0c8f72014-12-27 03:58:08 +00006789 Result R(MethList->getMethod(),
6790 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006791 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006792 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006793 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006794 }
6795 }
6796 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006797
6798 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006799}
Douglas Gregor6285f752010-04-06 16:40:00 +00006800
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006801void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006802 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006803 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006804 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006805
Douglas Gregor63745d52011-07-21 01:05:26 +00006806 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006807
Fangrui Song050229d2018-11-24 00:14:31 +00006808 ResultBuilder Results(
6809 *this, CodeCompleter->getAllocator(),
6810 CodeCompleter->getCodeCompletionTUInfo(),
6811 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6812 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006813
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006814 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006815 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006816
6817 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006818 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006819 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006820 // code-complete the expression using the corresponding parameter type as
6821 // our preferred type, improving completion results.
6822 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006823 QualType PreferredType =
6824 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006825 if (PreferredType.isNull())
6826 CodeCompleteOrdinaryName(S, PCC_Expression);
6827 else
6828 CodeCompleteExpression(S, PreferredType);
6829 return;
6830 }
6831
Fangrui Song050229d2018-11-24 00:14:31 +00006832 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006833 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006834}
6835
Richard Trieu2bd04012011-09-09 02:00:50 +00006836void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006837 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006838 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006839 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006840 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006841
Steve Naroffeae65032009-11-07 02:08:14 +00006842 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006843
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006844 // If necessary, apply function/array conversion to the receiver.
6845 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006846 if (RecExpr) {
6847 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6848 if (Conv.isInvalid()) // conversion failed. bail.
6849 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006850 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006851 }
Fangrui Song050229d2018-11-24 00:14:31 +00006852 QualType ReceiverType = RecExpr
6853 ? RecExpr->getType()
6854 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006855 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006856 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006857
Douglas Gregordc520b02010-11-08 21:12:30 +00006858 // If we're messaging an expression with type "id" or "Class", check
6859 // whether we know something special about the receiver that allows
6860 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006861 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006862 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6863 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006864 return CodeCompleteObjCClassMessage(
6865 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6866 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006867
Fangrui Song050229d2018-11-24 00:14:31 +00006868 ReceiverType =
6869 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006870 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006871 } else if (RecExpr && getLangOpts().CPlusPlus) {
6872 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6873 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006874 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006875 ReceiverType = RecExpr->getType();
6876 }
6877 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006878
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006879 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006880 ResultBuilder Results(
6881 *this, CodeCompleter->getAllocator(),
6882 CodeCompleter->getCodeCompletionTUInfo(),
6883 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6884 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006885
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006886 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006887
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006888 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006889 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006890 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006891 if (ObjCMethodDecl *SuperMethod =
6892 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006893 Results.Ignore(SuperMethod);
6894 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006895
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006896 // If we're inside an Objective-C method definition, prefer its selector to
6897 // others.
6898 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6899 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006900
Douglas Gregor1154e272010-09-16 16:06:31 +00006901 // Keep track of the selectors we've already added.
6902 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006903
Douglas Gregora3329fa2009-11-18 00:06:18 +00006904 // Handle messages to Class. This really isn't a message to an instance
6905 // method, so we treat it the same way we would treat a message send to a
6906 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006907 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006908 ReceiverType->isObjCQualifiedClassType()) {
6909 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6910 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006911 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6912 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006913 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006914 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006915 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006916 else if (const ObjCObjectPointerType *QualID =
6917 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006918 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006919 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006920 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6921 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006922 }
6923 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006924 else if (const ObjCObjectPointerType *IFacePtr =
6925 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006926 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006927 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006928 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006929
Douglas Gregora3329fa2009-11-18 00:06:18 +00006930 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006931 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006932 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6933 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006934 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006935 // Handle messages to "id".
6936 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006937 // We're messaging "id", so provide all instance methods we know
6938 // about as code-completion results.
6939
6940 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006941 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006942 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006943 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6944 I != N; ++I) {
6945 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006946 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006947 continue;
6948
Sebastian Redl75d8a322010-08-02 23:18:59 +00006949 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006950 }
6951 }
6952
Sebastian Redl75d8a322010-08-02 23:18:59 +00006953 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6954 MEnd = MethodPool.end();
6955 M != MEnd; ++M) {
6956 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006957 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006958 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006959 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006960
Nico Weber2e0c8f72014-12-27 03:58:08 +00006961 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006962 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006963
Nico Weber2e0c8f72014-12-27 03:58:08 +00006964 Result R(MethList->getMethod(),
6965 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006966 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006967 R.AllParametersAreInformative = false;
6968 Results.MaybeAddResult(R, CurContext);
6969 }
6970 }
6971 }
Steve Naroffeae65032009-11-07 02:08:14 +00006972 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006973
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006974 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006975 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006976 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006977 // code-complete the expression using the corresponding parameter type as
6978 // our preferred type, improving completion results.
6979 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006980 QualType PreferredType =
6981 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006982 if (PreferredType.isNull())
6983 CodeCompleteOrdinaryName(S, PCC_Expression);
6984 else
6985 CodeCompleteExpression(S, PreferredType);
6986 return;
6987 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006988
Fangrui Song050229d2018-11-24 00:14:31 +00006989 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6990 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006991}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006992
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006993void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006994 DeclGroupPtrTy IterationVar) {
6995 CodeCompleteExpressionData Data;
6996 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006997
Douglas Gregor68762e72010-08-23 21:17:50 +00006998 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006999 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00007000 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
7001 if (*I)
7002 Data.IgnoreDecls.push_back(*I);
7003 }
7004 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007005
Douglas Gregor68762e72010-08-23 21:17:50 +00007006 CodeCompleteExpression(S, Data);
7007}
7008
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007009void Sema::CodeCompleteObjCSelector(Scope *S,
7010 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007011 // If we have an external source, load the entire class method
7012 // pool from the AST file.
7013 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00007014 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
7015 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00007016 Selector Sel = ExternalSource->GetExternalSelector(I);
7017 if (Sel.isNull() || MethodPool.count(Sel))
7018 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007019
Douglas Gregor67c692c2010-08-26 15:07:07 +00007020 ReadMethodPool(Sel);
7021 }
7022 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007023
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007024 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007025 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007026 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00007027 Results.EnterNewScope();
7028 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007029 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00007030 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007031
Douglas Gregor67c692c2010-08-26 15:07:07 +00007032 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007033 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00007034 continue;
7035
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007036 CodeCompletionBuilder Builder(Results.getAllocator(),
7037 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007038 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007039 Builder.AddTypedTextChunk(
7040 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007041 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007042 continue;
7043 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007044
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007045 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00007046 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007047 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007048 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007049 Builder.AddInformativeChunk(
7050 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007051 Accumulator.clear();
7052 }
7053 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007054
Benjamin Kramer632500c2011-07-26 16:59:25 +00007055 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00007056 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00007057 }
Fangrui Song050229d2018-11-24 00:14:31 +00007058 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007059 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00007060 }
7061 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007062
7063 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00007064 Results.data(), Results.size());
7065}
7066
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007067/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00007068/// (translation unit) context.
7069static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007070 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00007071 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007072 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007073
Aaron Ballman629afae2014-03-07 19:56:05 +00007074 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00007075 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007076 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00007077 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00007078 Results.AddResult(
7079 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
7080 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007081 }
7082}
7083
Craig Topper883dd332015-12-24 23:58:11 +00007084void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00007085 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007086 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007087 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007088 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007089
Chandler Carruthede11632016-11-04 06:06:50 +00007090 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007091 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007092
Douglas Gregora3b23b02010-12-09 21:44:02 +00007093 // Tell the result set to ignore all of the protocols we have
7094 // already seen.
7095 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00007096 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00007097 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00007098 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007099
Douglas Gregora3b23b02010-12-09 21:44:02 +00007100 // Add all protocols.
7101 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
7102 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007103
Douglas Gregora3b23b02010-12-09 21:44:02 +00007104 Results.ExitScope();
7105 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00007106
7107 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7108 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00007109}
7110
7111void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007112 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007113 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007114 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007115
Chandler Carruthede11632016-11-04 06:06:50 +00007116 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00007117 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007118
Douglas Gregora3b23b02010-12-09 21:44:02 +00007119 // Add all protocols.
7120 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
7121 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00007122
Douglas Gregora3b23b02010-12-09 21:44:02 +00007123 Results.ExitScope();
7124 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00007125
7126 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7127 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00007128}
Douglas Gregor49c22a72009-11-18 16:26:39 +00007129
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007130/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00007131/// the given (translation unit) context.
7132static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
7133 bool OnlyForwardDeclarations,
7134 bool OnlyUnimplemented,
7135 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00007136 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007137
Aaron Ballman629afae2014-03-07 19:56:05 +00007138 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00007139 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00007140 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00007141 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00007142 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00007143 Results.AddResult(
7144 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
7145 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007146 }
7147}
7148
Eric Liuf5ba09f2018-07-04 10:01:18 +00007149void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007150 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007151 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007152 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007153 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007154
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007155 if (CodeCompleter->includeGlobals()) {
7156 // Add all classes.
7157 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7158 false, Results);
7159 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007160
Douglas Gregor49c22a72009-11-18 16:26:39 +00007161 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007162
Eric Liuf5ba09f2018-07-04 10:01:18 +00007163 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7164 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007165}
7166
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007167void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007168 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007169 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007170 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007171 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007172 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007173
Douglas Gregor49c22a72009-11-18 16:26:39 +00007174 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00007175 NamedDecl *CurClass =
7176 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007177 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00007178 Results.Ignore(CurClass);
7179
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007180 if (CodeCompleter->includeGlobals()) {
7181 // Add all classes.
7182 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7183 false, Results);
7184 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007185
Douglas Gregor49c22a72009-11-18 16:26:39 +00007186 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007187
Eric Liuf5ba09f2018-07-04 10:01:18 +00007188 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7189 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007190}
7191
Eric Liuf5ba09f2018-07-04 10:01:18 +00007192void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007193 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007194 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00007195 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00007196 Results.EnterNewScope();
7197
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007198 if (CodeCompleter->includeGlobals()) {
7199 // Add all unimplemented classes.
7200 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
7201 true, Results);
7202 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007203
Douglas Gregor49c22a72009-11-18 16:26:39 +00007204 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00007205
Eric Liuf5ba09f2018-07-04 10:01:18 +00007206 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7207 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00007208}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007209
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007210void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007211 IdentifierInfo *ClassName,
7212 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007213 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007214
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007215 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007216 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007217 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007218
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007219 // Ignore any categories we find that have already been implemented by this
7220 // interface.
7221 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00007222 NamedDecl *CurClass =
7223 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
7224 if (ObjCInterfaceDecl *Class =
7225 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007226 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007227 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007228 }
7229
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007230 // Add all of the categories we know about.
7231 Results.EnterNewScope();
7232 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007233 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00007234 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00007235 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00007236 Results.AddResult(
7237 Result(Category, Results.getBasePriority(Category), nullptr),
7238 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007239 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007240
7241 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7242 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007243}
7244
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007245void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007246 IdentifierInfo *ClassName,
7247 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00007248 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007249
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007250 // Find the corresponding interface. If we couldn't find the interface, the
7251 // program itself is ill-formed. However, we'll try to be helpful still by
7252 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00007253 NamedDecl *CurClass =
7254 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007255 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
7256 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00007257 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007258
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007259 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007260 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00007261 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007262
7263 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007264 // declarations in this class and any of its superclasses, except for
7265 // already-implemented categories in the class itself.
7266 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
7267 Results.EnterNewScope();
7268 bool IgnoreImplemented = true;
7269 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007270 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007271 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00007272 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00007273 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
7274 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007275 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007276
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007277 Class = Class->getSuperClass();
7278 IgnoreImplemented = false;
7279 }
7280 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007281
7282 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7283 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00007284}
Douglas Gregor5d649882009-11-18 22:32:06 +00007285
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007286void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00007287 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007288 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00007289 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00007290
7291 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007292 ObjCContainerDecl *Container =
7293 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7294 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7295 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007296 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00007297
7298 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007299 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00007300 for (const auto *D : Container->decls())
7301 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00007302 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007303
Douglas Gregor5d649882009-11-18 22:32:06 +00007304 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00007305 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00007306 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00007307 if (ObjCImplementationDecl *ClassImpl =
7308 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00007309 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007310 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00007311 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007312 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00007313 AddObjCProperties(CCContext,
7314 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007315 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00007316 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00007317 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007318
7319 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7320 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007321}
7322
Fangrui Song050229d2018-11-24 00:14:31 +00007323void Sema::CodeCompleteObjCPropertySynthesizeIvar(
7324 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00007325 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007326 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007327 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007328 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00007329
7330 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00007331 ObjCContainerDecl *Container =
7332 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
7333 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
7334 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007335 return;
7336
Douglas Gregor5d649882009-11-18 22:32:06 +00007337 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00007338 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00007339 if (ObjCImplementationDecl *ClassImpl =
7340 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00007341 Class = ClassImpl->getClassInterface();
7342 else
Fangrui Song050229d2018-11-24 00:14:31 +00007343 Class = cast<ObjCCategoryImplDecl>(Container)
7344 ->getCategoryDecl()
7345 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00007346
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007347 // Determine the type of the property we're synthesizing.
7348 QualType PropertyType = Context.getObjCIdType();
7349 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00007350 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
7351 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00007352 PropertyType =
7353 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007354
7355 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007356 Results.setPreferredType(PropertyType);
7357 }
7358 }
7359
Douglas Gregor5d649882009-11-18 22:32:06 +00007360 // Add all of the instance variables in this class and its superclasses.
7361 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00007362 bool SawSimilarlyNamedIvar = false;
7363 std::string NameWithPrefix;
7364 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00007365 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00007366 std::string NameWithSuffix = PropertyName->getName().str();
7367 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00007368 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007369 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00007370 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00007371 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
7372 CurContext, nullptr, false);
7373
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007374 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00007375 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007376 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00007377 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007378 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00007379 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007380
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007381 // Reduce the priority of this result by one, to give it a slight
7382 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007383 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007384 Results.data()[Results.size() - 1].Kind ==
7385 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007386 Results.data()[Results.size() - 1].Declaration == Ivar)
7387 Results.data()[Results.size() - 1].Priority--;
7388 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007389 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007390 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007391
Douglas Gregor331faa02011-04-18 14:13:53 +00007392 if (!SawSimilarlyNamedIvar) {
7393 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007394 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007395 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007396 typedef CodeCompletionResult Result;
7397 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007398 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007399 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007400
Douglas Gregor75acd922011-09-27 23:30:47 +00007401 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007402 Builder.AddResultTypeChunk(
7403 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007404 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007405 Results.AddResult(
7406 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007407 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007408
Douglas Gregor5d649882009-11-18 22:32:06 +00007409 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007410
7411 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7412 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007413}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007414
Douglas Gregor416b5752010-08-25 01:08:01 +00007415// Mapping from selectors to the methods that implement that selector, along
7416// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007417typedef llvm::DenseMap<Selector,
7418 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7419 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007420
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007421/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007422/// (and its superclasses, protocols, etc.) that meet the given
7423/// criteria. Insert those methods into the map of known methods,
7424/// indexed by selector so they can be easily found.
7425static void FindImplementableMethods(ASTContext &Context,
7426 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007427 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007428 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007429 KnownMethodsMap &KnownMethods,
7430 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007431 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007432 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007433 if (!IFace->hasDefinition())
7434 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007435
7436 IFace = IFace->getDefinition();
7437 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007438
Fangrui Song050229d2018-11-24 00:14:31 +00007439 const ObjCList<ObjCProtocolDecl> &Protocols =
7440 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007441 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007442 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007443 I != E; ++I)
7444 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007445 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007446
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007447 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007448 for (auto *Cat : IFace->visible_categories()) {
7449 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007450 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007451 }
7452
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007453 // Visit the superclass.
7454 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007455 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007456 WantInstanceMethods, ReturnType, KnownMethods,
7457 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007458 }
7459
7460 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7461 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007462 const ObjCList<ObjCProtocolDecl> &Protocols =
7463 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007464 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007465 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007466 I != E; ++I)
7467 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007468 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007469
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007470 // If this category is the original class, jump to the interface.
7471 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007472 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007473 WantInstanceMethods, ReturnType, KnownMethods,
7474 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007475 }
7476
7477 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007478 // Make sure we have a definition; that's what we'll walk.
7479 if (!Protocol->hasDefinition())
7480 return;
7481 Protocol = Protocol->getDefinition();
7482 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007483
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007484 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007485 const ObjCList<ObjCProtocolDecl> &Protocols =
7486 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007487 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007488 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007489 I != E; ++I)
7490 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7491 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007492 }
7493
7494 // Add methods in this container. This operation occurs last because
7495 // we want the methods from this container to override any methods
7496 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007497 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007498 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007499 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007500 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007501 continue;
7502
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007503 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007504 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007505 }
7506 }
7507}
7508
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007509/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007510/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007511static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007512 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007513 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007514 CodeCompletionBuilder &Builder) {
7515 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007516 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007517 if (!Quals.empty())
7518 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007519 Builder.AddTextChunk(
7520 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007521 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7522}
7523
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007524/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007525/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007526static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007527 if (!Class)
7528 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007529
Douglas Gregor669a25a2011-02-17 00:22:45 +00007530 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7531 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007532
Douglas Gregor669a25a2011-02-17 00:22:45 +00007533 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7534}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007535
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007536/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007537/// Key-Value Observing (KVO).
7538static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7539 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007540 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007541 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007542 ResultBuilder &Results) {
7543 IdentifierInfo *PropName = Property->getIdentifier();
7544 if (!PropName || PropName->getLength() == 0)
7545 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007546
Douglas Gregor75acd922011-09-27 23:30:47 +00007547 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7548
Douglas Gregor669a25a2011-02-17 00:22:45 +00007549 // Builder that will create each code completion.
7550 typedef CodeCompletionResult Result;
7551 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007552 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007553
Douglas Gregor669a25a2011-02-17 00:22:45 +00007554 // The selector table.
7555 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007556
Douglas Gregor669a25a2011-02-17 00:22:45 +00007557 // The property name, copied into the code completion allocation region
7558 // on demand.
7559 struct KeyHolder {
7560 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007561 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007562 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007563
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007564 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007565 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007566
Douglas Gregor669a25a2011-02-17 00:22:45 +00007567 operator const char *() {
7568 if (CopiedKey)
7569 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007570
Douglas Gregor669a25a2011-02-17 00:22:45 +00007571 return CopiedKey = Allocator.CopyString(Key);
7572 }
7573 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007574
Douglas Gregor669a25a2011-02-17 00:22:45 +00007575 // The uppercased name of the property name.
7576 std::string UpperKey = PropName->getName();
7577 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007578 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007579
Fangrui Song050229d2018-11-24 00:14:31 +00007580 bool ReturnTypeMatchesProperty =
7581 ReturnType.isNull() ||
7582 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7583 Property->getType());
7584 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007585
Douglas Gregor669a25a2011-02-17 00:22:45 +00007586 // Add the normal accessor -(type)key.
7587 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007588 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007589 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7590 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007591 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7592 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007593
Douglas Gregor669a25a2011-02-17 00:22:45 +00007594 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007595 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007596 CXCursor_ObjCInstanceMethodDecl));
7597 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007598
Douglas Gregor669a25a2011-02-17 00:22:45 +00007599 // If we have an integral or boolean property (or the user has provided
7600 // an integral or boolean return type), add the accessor -(type)isKey.
7601 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007602 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007603 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007604 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7605 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007606 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007607 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007608 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7609 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007610 if (ReturnType.isNull()) {
7611 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7612 Builder.AddTextChunk("BOOL");
7613 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7614 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007615
Fangrui Song050229d2018-11-24 00:14:31 +00007616 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007617 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007618 CXCursor_ObjCInstanceMethodDecl));
7619 }
7620 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007621
Douglas Gregor669a25a2011-02-17 00:22:45 +00007622 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007623 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007624 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007625 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007626 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007627 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007628 if (ReturnType.isNull()) {
7629 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7630 Builder.AddTextChunk("void");
7631 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7632 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007633
Fangrui Song050229d2018-11-24 00:14:31 +00007634 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007635 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007636 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7637 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007638 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007639 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007640 CXCursor_ObjCInstanceMethodDecl));
7641 }
7642 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007643
Douglas Gregor669a25a2011-02-17 00:22:45 +00007644 // Indexed and unordered accessors
7645 unsigned IndexedGetterPriority = CCP_CodePattern;
7646 unsigned IndexedSetterPriority = CCP_CodePattern;
7647 unsigned UnorderedGetterPriority = CCP_CodePattern;
7648 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007649 if (const auto *ObjCPointer =
7650 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007651 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7652 // If this interface type is not provably derived from a known
7653 // collection, penalize the corresponding completions.
7654 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007655 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007656 if (!InheritsFromClassNamed(IFace, "NSArray"))
7657 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7658 }
7659
7660 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007661 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007662 if (!InheritsFromClassNamed(IFace, "NSSet"))
7663 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7664 }
7665 }
7666 } else {
7667 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7668 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7669 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7670 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7671 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007672
Douglas Gregor669a25a2011-02-17 00:22:45 +00007673 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007674 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007675 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007676 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007677 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007678 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7679 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007680 if (ReturnType.isNull()) {
7681 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7682 Builder.AddTextChunk("NSUInteger");
7683 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7684 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007685
Fangrui Song050229d2018-11-24 00:14:31 +00007686 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7687 Results.AddResult(
7688 Result(Builder.TakeString(),
7689 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7690 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007691 }
7692 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007693
Douglas Gregor669a25a2011-02-17 00:22:45 +00007694 // Indexed getters
7695 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7696 if (IsInstanceMethod &&
7697 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007698 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007699 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007700 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007701 if (ReturnType.isNull()) {
7702 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7703 Builder.AddTextChunk("id");
7704 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7705 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007706
Douglas Gregor669a25a2011-02-17 00:22:45 +00007707 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7708 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7709 Builder.AddTextChunk("NSUInteger");
7710 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7711 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007712 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007713 CXCursor_ObjCInstanceMethodDecl));
7714 }
7715 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007716
Douglas Gregor669a25a2011-02-17 00:22:45 +00007717 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7718 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007719 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007720 (ReturnType->isObjCObjectPointerType() &&
7721 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007722 ReturnType->getAs<ObjCObjectPointerType>()
7723 ->getInterfaceDecl()
7724 ->getName() == "NSArray"))) {
7725 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007726 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007727 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007728 if (ReturnType.isNull()) {
7729 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7730 Builder.AddTextChunk("NSArray *");
7731 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7732 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007733
Douglas Gregor669a25a2011-02-17 00:22:45 +00007734 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7735 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7736 Builder.AddTextChunk("NSIndexSet *");
7737 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7738 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007739 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007740 CXCursor_ObjCInstanceMethodDecl));
7741 }
7742 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007743
Douglas Gregor669a25a2011-02-17 00:22:45 +00007744 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7745 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007746 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007747 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7748 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007749
David Blaikie82e95a32014-11-19 07:49:47 +00007750 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007751 if (ReturnType.isNull()) {
7752 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7753 Builder.AddTextChunk("void");
7754 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7755 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007756
Douglas Gregor669a25a2011-02-17 00:22:45 +00007757 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7758 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7759 Builder.AddPlaceholderChunk("object-type");
7760 Builder.AddTextChunk(" **");
7761 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7762 Builder.AddTextChunk("buffer");
7763 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7764 Builder.AddTypedTextChunk("range:");
7765 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7766 Builder.AddTextChunk("NSRange");
7767 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7768 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007769 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007770 CXCursor_ObjCInstanceMethodDecl));
7771 }
7772 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007773
Douglas Gregor669a25a2011-02-17 00:22:45 +00007774 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007775
Douglas Gregor669a25a2011-02-17 00:22:45 +00007776 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7777 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007778 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007779 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7780 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007781
David Blaikie82e95a32014-11-19 07:49:47 +00007782 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007783 if (ReturnType.isNull()) {
7784 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7785 Builder.AddTextChunk("void");
7786 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7787 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007788
Douglas Gregor669a25a2011-02-17 00:22:45 +00007789 Builder.AddTypedTextChunk("insertObject:");
7790 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7791 Builder.AddPlaceholderChunk("object-type");
7792 Builder.AddTextChunk(" *");
7793 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7794 Builder.AddTextChunk("object");
7795 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7796 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7797 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7798 Builder.AddPlaceholderChunk("NSUInteger");
7799 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7800 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007801 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007802 CXCursor_ObjCInstanceMethodDecl));
7803 }
7804 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007805
Douglas Gregor669a25a2011-02-17 00:22:45 +00007806 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7807 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007808 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007809 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7810 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007811
David Blaikie82e95a32014-11-19 07:49:47 +00007812 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007813 if (ReturnType.isNull()) {
7814 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7815 Builder.AddTextChunk("void");
7816 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7817 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007818
Douglas Gregor669a25a2011-02-17 00:22:45 +00007819 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7820 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7821 Builder.AddTextChunk("NSArray *");
7822 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7823 Builder.AddTextChunk("array");
7824 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7825 Builder.AddTypedTextChunk("atIndexes:");
7826 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7827 Builder.AddPlaceholderChunk("NSIndexSet *");
7828 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7829 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007830 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007831 CXCursor_ObjCInstanceMethodDecl));
7832 }
7833 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007834
Douglas Gregor669a25a2011-02-17 00:22:45 +00007835 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7836 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007837 std::string SelectorName =
7838 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007839 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007840 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007841 if (ReturnType.isNull()) {
7842 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7843 Builder.AddTextChunk("void");
7844 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7845 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007846
Douglas Gregor669a25a2011-02-17 00:22:45 +00007847 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7849 Builder.AddTextChunk("NSUInteger");
7850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7851 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007852 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007853 CXCursor_ObjCInstanceMethodDecl));
7854 }
7855 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007856
Douglas Gregor669a25a2011-02-17 00:22:45 +00007857 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7858 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007859 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007860 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007861 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007862 if (ReturnType.isNull()) {
7863 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7864 Builder.AddTextChunk("void");
7865 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7866 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007867
Douglas Gregor669a25a2011-02-17 00:22:45 +00007868 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7869 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7870 Builder.AddTextChunk("NSIndexSet *");
7871 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7872 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007873 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007874 CXCursor_ObjCInstanceMethodDecl));
7875 }
7876 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007877
Douglas Gregor669a25a2011-02-17 00:22:45 +00007878 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7879 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007880 std::string SelectorName =
7881 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7882 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7883 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007884
David Blaikie82e95a32014-11-19 07:49:47 +00007885 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007886 if (ReturnType.isNull()) {
7887 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7888 Builder.AddTextChunk("void");
7889 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7890 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007891
Douglas Gregor669a25a2011-02-17 00:22:45 +00007892 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7893 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7894 Builder.AddPlaceholderChunk("NSUInteger");
7895 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7896 Builder.AddTextChunk("index");
7897 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7898 Builder.AddTypedTextChunk("withObject:");
7899 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7900 Builder.AddTextChunk("id");
7901 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7902 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007903 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007904 CXCursor_ObjCInstanceMethodDecl));
7905 }
7906 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007907
Douglas Gregor669a25a2011-02-17 00:22:45 +00007908 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7909 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007910 std::string SelectorName1 =
7911 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007912 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007913 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7914 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007915
David Blaikie82e95a32014-11-19 07:49:47 +00007916 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007917 if (ReturnType.isNull()) {
7918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7919 Builder.AddTextChunk("void");
7920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7921 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007922
Douglas Gregor669a25a2011-02-17 00:22:45 +00007923 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7924 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7925 Builder.AddPlaceholderChunk("NSIndexSet *");
7926 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7927 Builder.AddTextChunk("indexes");
7928 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7929 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7930 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7931 Builder.AddTextChunk("NSArray *");
7932 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7933 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007934 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007935 CXCursor_ObjCInstanceMethodDecl));
7936 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007937 }
7938
Douglas Gregor669a25a2011-02-17 00:22:45 +00007939 // Unordered getters
7940 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007941 if (IsInstanceMethod &&
7942 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007943 (ReturnType->isObjCObjectPointerType() &&
7944 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007945 ReturnType->getAs<ObjCObjectPointerType>()
7946 ->getInterfaceDecl()
7947 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007948 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007949 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007950 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7951 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007952 if (ReturnType.isNull()) {
7953 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7954 Builder.AddTextChunk("NSEnumerator *");
7955 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7956 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007957
Douglas Gregor669a25a2011-02-17 00:22:45 +00007958 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007959 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007960 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007961 }
7962 }
7963
7964 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007965 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007966 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007967 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007968 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007969 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007970 if (ReturnType.isNull()) {
7971 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7972 Builder.AddPlaceholderChunk("object-type");
7973 Builder.AddTextChunk(" *");
7974 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7975 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007976
Douglas Gregor669a25a2011-02-17 00:22:45 +00007977 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7978 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7979 if (ReturnType.isNull()) {
7980 Builder.AddPlaceholderChunk("object-type");
7981 Builder.AddTextChunk(" *");
7982 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007983 Builder.AddTextChunk(GetCompletionTypeString(
7984 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007985 }
7986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7987 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007988 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007989 CXCursor_ObjCInstanceMethodDecl));
7990 }
7991 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007992
Douglas Gregor669a25a2011-02-17 00:22:45 +00007993 // Mutable unordered accessors
7994 // - (void)addKeyObject:(type *)object
7995 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007996 std::string SelectorName =
7997 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007998 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007999 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008000 if (ReturnType.isNull()) {
8001 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8002 Builder.AddTextChunk("void");
8003 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8004 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008005
Douglas Gregor669a25a2011-02-17 00:22:45 +00008006 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8007 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8008 Builder.AddPlaceholderChunk("object-type");
8009 Builder.AddTextChunk(" *");
8010 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8011 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008012 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008013 CXCursor_ObjCInstanceMethodDecl));
8014 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008015 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008016
8017 // - (void)addKey:(NSSet *)objects
8018 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008019 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008020 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008021 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008022 if (ReturnType.isNull()) {
8023 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8024 Builder.AddTextChunk("void");
8025 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8026 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008027
Douglas Gregor669a25a2011-02-17 00:22:45 +00008028 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8029 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8030 Builder.AddTextChunk("NSSet *");
8031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8032 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008033 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008034 CXCursor_ObjCInstanceMethodDecl));
8035 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008036 }
8037
Douglas Gregor669a25a2011-02-17 00:22:45 +00008038 // - (void)removeKeyObject:(type *)object
8039 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00008040 std::string SelectorName =
8041 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008042 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008043 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008044 if (ReturnType.isNull()) {
8045 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8046 Builder.AddTextChunk("void");
8047 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8048 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008049
Douglas Gregor669a25a2011-02-17 00:22:45 +00008050 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8051 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8052 Builder.AddPlaceholderChunk("object-type");
8053 Builder.AddTextChunk(" *");
8054 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8055 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008056 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008057 CXCursor_ObjCInstanceMethodDecl));
8058 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008059 }
8060
Douglas Gregor669a25a2011-02-17 00:22:45 +00008061 // - (void)removeKey:(NSSet *)objects
8062 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008063 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008064 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008065 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008066 if (ReturnType.isNull()) {
8067 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8068 Builder.AddTextChunk("void");
8069 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8070 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008071
Douglas Gregor669a25a2011-02-17 00:22:45 +00008072 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8073 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8074 Builder.AddTextChunk("NSSet *");
8075 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8076 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008077 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008078 CXCursor_ObjCInstanceMethodDecl));
8079 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008080 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008081
8082 // - (void)intersectKey:(NSSet *)objects
8083 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008084 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008085 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008086 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008087 if (ReturnType.isNull()) {
8088 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8089 Builder.AddTextChunk("void");
8090 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8091 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008092
Douglas Gregor669a25a2011-02-17 00:22:45 +00008093 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
8094 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8095 Builder.AddTextChunk("NSSet *");
8096 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8097 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008098 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00008099 CXCursor_ObjCInstanceMethodDecl));
8100 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008101 }
8102
Douglas Gregor669a25a2011-02-17 00:22:45 +00008103 // Key-Value Observing
8104 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008105 if (!IsInstanceMethod &&
8106 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00008107 (ReturnType->isObjCObjectPointerType() &&
8108 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00008109 ReturnType->getAs<ObjCObjectPointerType>()
8110 ->getInterfaceDecl()
8111 ->getName() == "NSSet"))) {
8112 std::string SelectorName =
8113 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00008114 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008115 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8116 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00008117 if (ReturnType.isNull()) {
8118 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00008119 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00008120 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8121 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008122
Douglas Gregor669a25a2011-02-17 00:22:45 +00008123 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008124 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008125 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00008126 }
8127 }
8128
8129 // + (BOOL)automaticallyNotifiesObserversForKey
8130 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00008131 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00008132 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00008133 std::string SelectorName =
8134 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00008135 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00008136 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
8137 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00008138 if (ReturnType.isNull()) {
8139 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8140 Builder.AddTextChunk("BOOL");
8141 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8142 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008143
Douglas Gregor857bcda2011-06-02 04:02:27 +00008144 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008145 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00008146 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00008147 }
8148 }
8149}
8150
Alex Lorenzb8740422017-10-24 16:39:37 +00008151void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008152 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008153 // Determine the return type of the method we're declaring, if
8154 // provided.
8155 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00008156 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008157 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00008158 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
8159 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00008160 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008161 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00008162 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00008163 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00008164 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008165 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
8166 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008167 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00008168 } else if (ObjCCategoryImplDecl *CatImpl =
8169 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008170 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008171 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008172 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00008173 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008174 }
8175
8176 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00008177 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00008178 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008179 }
8180
Douglas Gregor1b035bb2010-10-18 18:21:28 +00008181 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008182 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008183 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008184 return;
8185 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008186
Douglas Gregor636a61e2010-04-07 00:21:17 +00008187 // Find all of the methods that we could declare/implement here.
8188 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00008189 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
8190 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008191
Douglas Gregor636a61e2010-04-07 00:21:17 +00008192 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00008193 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008194 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008195 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008196 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008197 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00008198 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008199 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008200 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008201 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008202 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008203 CodeCompletionBuilder Builder(Results.getAllocator(),
8204 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00008205
8206 // Add the '-'/'+' prefix if it wasn't provided yet.
8207 if (!IsInstanceMethod) {
8208 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
8209 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8210 }
8211
Douglas Gregor636a61e2010-04-07 00:21:17 +00008212 // If the result type was not already provided, add it to the
8213 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008214 if (ReturnType.isNull()) {
8215 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
8216 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00008217 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
8218 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008219 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008220
8221 Selector Sel = Method->getSelector();
8222
8223 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00008224 Builder.AddTypedTextChunk(
8225 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008226
8227 // Add parameters to the pattern.
8228 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008229 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008230 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00008231 P != PEnd; (void)++P, ++I) {
8232 // Add the part of the selector name.
8233 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008234 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00008235 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008236 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8237 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00008238 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008239 } else
8240 break;
8241
8242 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00008243 QualType ParamType;
8244 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
8245 ParamType = (*P)->getType();
8246 else
8247 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00008248 ParamType = ParamType.substObjCTypeArgs(
8249 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00008250 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00008251 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
8252 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008253
Douglas Gregor636a61e2010-04-07 00:21:17 +00008254 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00008255 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008256 }
8257
8258 if (Method->isVariadic()) {
8259 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008260 Builder.AddChunk(CodeCompletionString::CK_Comma);
8261 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008262 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00008263
Douglas Gregord37c59d2010-05-28 00:57:46 +00008264 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008265 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008266 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8267 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
8268 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00008269 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00008270 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008271 Builder.AddTextChunk("return");
8272 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8273 Builder.AddPlaceholderChunk("expression");
8274 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008275 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008276 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008277
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008278 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
8279 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00008280 }
8281
Douglas Gregor416b5752010-08-25 01:08:01 +00008282 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00008283 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00008284 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00008285 setInBaseClass(R);
8286 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00008287 }
8288
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008289 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00008290 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008291 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00008292 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00008293 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008294
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008295 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008296 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008297 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00008298 M != MEnd; ++M)
8299 KnownSelectors.insert(M->first);
8300
Douglas Gregor669a25a2011-02-17 00:22:45 +00008301 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
8302 if (!IFace)
8303 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
8304 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008305
Aaron Ballman3fe486a2014-03-13 21:23:55 +00008306 if (IFace)
8307 for (auto *Cat : IFace->visible_categories())
8308 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00008309
8310 if (IsInstanceMethod) {
8311 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
8312 for (auto *P : Containers[I]->instance_properties())
8313 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
8314 KnownSelectors, Results);
8315 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00008316 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008317
Douglas Gregor636a61e2010-04-07 00:21:17 +00008318 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008319
8320 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8321 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00008322}
Douglas Gregor95887f92010-07-08 23:20:03 +00008323
Fangrui Song050229d2018-11-24 00:14:31 +00008324void Sema::CodeCompleteObjCMethodDeclSelector(
8325 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
8326 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008327 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00008328 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00008329 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00008330 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
8331 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00008332 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00008333 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00008334 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00008335
8336 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00008337 }
8338 }
8339
8340 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00008341 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008342 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008343 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008344 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008345
Douglas Gregor95887f92010-07-08 23:20:03 +00008346 if (ReturnTy)
8347 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00008348
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008349 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00008350 for (GlobalMethodPool::iterator M = MethodPool.begin(),
8351 MEnd = MethodPool.end();
8352 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008353 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
8354 : &M->second.second;
8355 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00008356 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00008357 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008358
Douglas Gregor45879692010-07-08 23:37:41 +00008359 if (AtParameterName) {
8360 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008361 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00008362 if (NumSelIdents &&
8363 NumSelIdents <= MethList->getMethod()->param_size()) {
8364 ParmVarDecl *Param =
8365 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00008366 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008367 CodeCompletionBuilder Builder(Results.getAllocator(),
8368 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00008369 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00008370 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008371 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00008372 }
8373 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008374
Douglas Gregor45879692010-07-08 23:37:41 +00008375 continue;
8376 }
Craig Topperc3ec1492014-05-26 06:22:03 +00008377
Nico Weber2e0c8f72014-12-27 03:58:08 +00008378 Result R(MethList->getMethod(),
8379 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00008380 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00008381 R.AllParametersAreInformative = false;
8382 R.DeclaringEntity = true;
8383 Results.MaybeAddResult(R, CurContext);
8384 }
8385 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008386
Douglas Gregor95887f92010-07-08 23:20:03 +00008387 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008388
8389 if (!AtParameterName && !SelIdents.empty() &&
8390 SelIdents.front()->getName().startswith("init")) {
8391 for (const auto &M : PP.macros()) {
8392 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8393 continue;
8394 Results.EnterNewScope();
8395 CodeCompletionBuilder Builder(Results.getAllocator(),
8396 Results.getCodeCompletionTUInfo());
8397 Builder.AddTypedTextChunk(
8398 Builder.getAllocator().CopyString(M.first->getName()));
8399 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8400 CXCursor_MacroDefinition));
8401 Results.ExitScope();
8402 }
8403 }
8404
Eric Liuf5ba09f2018-07-04 10:01:18 +00008405 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8406 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008407}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008408
Douglas Gregorec00a262010-08-24 22:20:20 +00008409void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008410 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008411 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008412 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008413 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008414
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008415 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008416 CodeCompletionBuilder Builder(Results.getAllocator(),
8417 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008418 Builder.AddTypedTextChunk("if");
8419 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8420 Builder.AddPlaceholderChunk("condition");
8421 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008422
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008423 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008424 Builder.AddTypedTextChunk("ifdef");
8425 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8426 Builder.AddPlaceholderChunk("macro");
8427 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008428
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008429 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008430 Builder.AddTypedTextChunk("ifndef");
8431 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8432 Builder.AddPlaceholderChunk("macro");
8433 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008434
8435 if (InConditional) {
8436 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008437 Builder.AddTypedTextChunk("elif");
8438 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8439 Builder.AddPlaceholderChunk("condition");
8440 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008441
8442 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008443 Builder.AddTypedTextChunk("else");
8444 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008445
8446 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008447 Builder.AddTypedTextChunk("endif");
8448 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008449 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008450
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008451 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008452 Builder.AddTypedTextChunk("include");
8453 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8454 Builder.AddTextChunk("\"");
8455 Builder.AddPlaceholderChunk("header");
8456 Builder.AddTextChunk("\"");
8457 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008458
8459 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008460 Builder.AddTypedTextChunk("include");
8461 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8462 Builder.AddTextChunk("<");
8463 Builder.AddPlaceholderChunk("header");
8464 Builder.AddTextChunk(">");
8465 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008466
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008467 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008468 Builder.AddTypedTextChunk("define");
8469 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8470 Builder.AddPlaceholderChunk("macro");
8471 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008472
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008473 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008474 Builder.AddTypedTextChunk("define");
8475 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8476 Builder.AddPlaceholderChunk("macro");
8477 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8478 Builder.AddPlaceholderChunk("args");
8479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8480 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008481
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008482 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008483 Builder.AddTypedTextChunk("undef");
8484 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8485 Builder.AddPlaceholderChunk("macro");
8486 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008487
8488 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008489 Builder.AddTypedTextChunk("line");
8490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8491 Builder.AddPlaceholderChunk("number");
8492 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008493
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008494 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008495 Builder.AddTypedTextChunk("line");
8496 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8497 Builder.AddPlaceholderChunk("number");
8498 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8499 Builder.AddTextChunk("\"");
8500 Builder.AddPlaceholderChunk("filename");
8501 Builder.AddTextChunk("\"");
8502 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008503
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008504 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008505 Builder.AddTypedTextChunk("error");
8506 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8507 Builder.AddPlaceholderChunk("message");
8508 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008509
8510 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008511 Builder.AddTypedTextChunk("pragma");
8512 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8513 Builder.AddPlaceholderChunk("arguments");
8514 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008515
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008516 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008517 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008518 Builder.AddTypedTextChunk("import");
8519 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8520 Builder.AddTextChunk("\"");
8521 Builder.AddPlaceholderChunk("header");
8522 Builder.AddTextChunk("\"");
8523 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008524
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008525 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008526 Builder.AddTypedTextChunk("import");
8527 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8528 Builder.AddTextChunk("<");
8529 Builder.AddPlaceholderChunk("header");
8530 Builder.AddTextChunk(">");
8531 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008532 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008533
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008534 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008535 Builder.AddTypedTextChunk("include_next");
8536 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8537 Builder.AddTextChunk("\"");
8538 Builder.AddPlaceholderChunk("header");
8539 Builder.AddTextChunk("\"");
8540 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008541
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008542 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008543 Builder.AddTypedTextChunk("include_next");
8544 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8545 Builder.AddTextChunk("<");
8546 Builder.AddPlaceholderChunk("header");
8547 Builder.AddTextChunk(">");
8548 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008549
8550 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008551 Builder.AddTypedTextChunk("warning");
8552 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8553 Builder.AddPlaceholderChunk("message");
8554 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008555
8556 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8557 // completions for them. And __include_macros is a Clang-internal extension
8558 // that we don't want to encourage anyone to use.
8559
8560 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8561 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008562
8563 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008564 Results.data(), Results.size());
8565}
8566
8567void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008568 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8569 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008570}
8571
Douglas Gregorec00a262010-08-24 22:20:20 +00008572void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008573 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008574 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008575 IsDefinition ? CodeCompletionContext::CCC_MacroName
8576 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008577 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008578 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008579 CodeCompletionBuilder Builder(Results.getAllocator(),
8580 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008581 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008582 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008583 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008584 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008585 Builder.AddTypedTextChunk(
8586 Builder.getAllocator().CopyString(M->first->getName()));
8587 Results.AddResult(CodeCompletionResult(
8588 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008589 }
8590 Results.ExitScope();
8591 } else if (IsDefinition) {
8592 // FIXME: Can we detect when the user just wrote an include guard above?
8593 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008594
Douglas Gregor0ac41382010-09-23 23:01:17 +00008595 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008596 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008597}
8598
Douglas Gregorec00a262010-08-24 22:20:20 +00008599void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008600 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008601 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008602 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008603
Douglas Gregorec00a262010-08-24 22:20:20 +00008604 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008605 AddMacroResults(PP, Results,
Sam McCall36082e32019-07-18 07:17:49 +00008606 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008607
Fangrui Song050229d2018-11-24 00:14:31 +00008608 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008609 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008610 CodeCompletionBuilder Builder(Results.getAllocator(),
8611 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008612 Builder.AddTypedTextChunk("defined");
8613 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8614 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8615 Builder.AddPlaceholderChunk("macro");
8616 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8617 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008618 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008619
8620 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8621 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008622}
8623
8624void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8625 IdentifierInfo *Macro,
8626 MacroInfo *MacroInfo,
8627 unsigned Argument) {
8628 // FIXME: In the future, we could provide "overload" results, much like we
8629 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008630
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008631 // Now just ignore this. There will be another code-completion callback
8632 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008633}
8634
Sam McCall3d8051a2018-09-18 08:40:41 +00008635// This handles completion inside an #include filename, e.g. #include <foo/ba
8636// We look for the directory "foo" under each directory on the include path,
8637// list its files, and reassemble the appropriate #include.
8638void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8639 // RelDir should use /, but unescaped \ is possible on windows!
8640 // Our completions will normalize to / for simplicity, this case is rare.
8641 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8642 // We need the native slashes for the actual file system interactions.
8643 SmallString<128> NativeRelDir = StringRef(RelDir);
8644 llvm::sys::path::native(NativeRelDir);
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008645 llvm::vfs::FileSystem &FS =
8646 getSourceManager().getFileManager().getVirtualFileSystem();
Sam McCall3d8051a2018-09-18 08:40:41 +00008647
8648 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8649 CodeCompleter->getCodeCompletionTUInfo(),
8650 CodeCompletionContext::CCC_IncludedFile);
8651 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8652
8653 // Helper: adds one file or directory completion result.
8654 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8655 SmallString<64> TypedChunk = Filename;
8656 // Directory completion is up to the slash, e.g. <sys/
8657 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8658 auto R = SeenResults.insert(TypedChunk);
8659 if (R.second) { // New completion
8660 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8661 *R.first = InternedTyped; // Avoid dangling StringRef.
8662 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8663 CodeCompleter->getCodeCompletionTUInfo());
8664 Builder.AddTypedTextChunk(InternedTyped);
8665 // The result is a "Pattern", which is pretty opaque.
8666 // We may want to include the real filename to allow smart ranking.
8667 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8668 }
8669 };
8670
8671 // Helper: scans IncludeDir for nice files, and adds results for each.
David Goldman3e804d22019-02-27 17:40:33 +00008672 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
8673 bool IsSystem,
8674 DirectoryLookup::LookupType_t LookupType) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008675 llvm::SmallString<128> Dir = IncludeDir;
David Goldman3e804d22019-02-27 17:40:33 +00008676 if (!NativeRelDir.empty()) {
8677 if (LookupType == DirectoryLookup::LT_Framework) {
8678 // For a framework dir, #include <Foo/Bar/> actually maps to
8679 // a path of Foo.framework/Headers/Bar/.
8680 auto Begin = llvm::sys::path::begin(NativeRelDir);
8681 auto End = llvm::sys::path::end(NativeRelDir);
8682
8683 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
8684 llvm::sys::path::append(Dir, ++Begin, End);
8685 } else {
8686 llvm::sys::path::append(Dir, NativeRelDir);
8687 }
8688 }
Sam McCall3d8051a2018-09-18 08:40:41 +00008689
8690 std::error_code EC;
8691 unsigned Count = 0;
Duncan P. N. Exon Smithdb8a7422019-03-26 22:32:06 +00008692 for (auto It = FS.dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008693 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008694 if (++Count == 2500) // If we happen to hit a huge directory,
8695 break; // bail out early so we're not too slow.
8696 StringRef Filename = llvm::sys::path::filename(It->path());
8697 switch (It->type()) {
8698 case llvm::sys::fs::file_type::directory_file:
David Goldman3e804d22019-02-27 17:40:33 +00008699 // All entries in a framework directory must have a ".framework" suffix,
8700 // but the suffix does not appear in the source code's include/import.
8701 if (LookupType == DirectoryLookup::LT_Framework &&
8702 NativeRelDir.empty() && !Filename.consume_back(".framework"))
8703 break;
8704
Sam McCall3d8051a2018-09-18 08:40:41 +00008705 AddCompletion(Filename, /*IsDirectory=*/true);
8706 break;
8707 case llvm::sys::fs::file_type::regular_file:
8708 // Only files that really look like headers. (Except in system dirs).
8709 if (!IsSystem) {
8710 // Header extensions from Types.def, which we can't depend on here.
8711 if (!(Filename.endswith_lower(".h") ||
8712 Filename.endswith_lower(".hh") ||
8713 Filename.endswith_lower(".hpp") ||
8714 Filename.endswith_lower(".inc")))
8715 break;
8716 }
8717 AddCompletion(Filename, /*IsDirectory=*/false);
8718 break;
8719 default:
8720 break;
8721 }
8722 }
8723 };
8724
8725 // Helper: adds results relative to IncludeDir, if possible.
8726 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8727 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008728 switch (IncludeDir.getLookupType()) {
8729 case DirectoryLookup::LT_HeaderMap:
8730 // header maps are not (currently) enumerable.
8731 break;
8732 case DirectoryLookup::LT_NormalDir:
David Goldman3e804d22019-02-27 17:40:33 +00008733 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
8734 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008735 break;
8736 case DirectoryLookup::LT_Framework:
David Goldman3e804d22019-02-27 17:40:33 +00008737 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
8738 DirectoryLookup::LT_Framework);
Sam McCall3d8051a2018-09-18 08:40:41 +00008739 break;
8740 }
8741 };
8742
8743 // Finally with all our helpers, we can scan the include path.
8744 // Do this in standard order so deduplication keeps the right file.
8745 // (In case we decide to add more details to the results later).
8746 const auto &S = PP.getHeaderSearchInfo();
8747 using llvm::make_range;
8748 if (!Angled) {
8749 // The current directory is on the include path for "quoted" includes.
8750 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8751 if (CurFile && CurFile->getDir())
David Goldman3e804d22019-02-27 17:40:33 +00008752 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
8753 DirectoryLookup::LT_NormalDir);
Sam McCall3d8051a2018-09-18 08:40:41 +00008754 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8755 AddFilesFromDirLookup(D, false);
8756 }
8757 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008758 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008759 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8760 AddFilesFromDirLookup(D, true);
8761
8762 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8763 Results.data(), Results.size());
8764}
8765
Douglas Gregor11583702010-08-25 17:04:25 +00008766void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008767 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008768 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8769 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008770}
8771
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008772void Sema::CodeCompleteAvailabilityPlatformName() {
8773 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8774 CodeCompleter->getCodeCompletionTUInfo(),
8775 CodeCompletionContext::CCC_Other);
8776 Results.EnterNewScope();
8777 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8778 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8779 Results.AddResult(CodeCompletionResult(Platform));
8780 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8781 Twine(Platform) + "ApplicationExtension")));
8782 }
8783 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008784 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8785 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008786}
8787
Fangrui Song050229d2018-11-24 00:14:31 +00008788void Sema::GatherGlobalCodeCompletions(
8789 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8790 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008791 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8792 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008793 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008794 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008795 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008796 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8797 Consumer,
8798 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008799 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008800
Douglas Gregorb14904c2010-08-13 22:48:40 +00008801 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008802 AddMacroResults(PP, Builder,
Sam McCall36082e32019-07-18 07:17:49 +00008803 !CodeCompleter || CodeCompleter->loadExternal(), true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008804
Douglas Gregorb14904c2010-08-13 22:48:40 +00008805 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008806 Results.insert(Results.end(), Builder.data(),
8807 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008808}