blob: ab18d7fb5e0257b9ebc126f4fe5a5a5bec232238 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Douglas Gregor2436e712009-09-17 21:32:03 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the code-completion semantic actions.
10//
11//===----------------------------------------------------------------------===//
Eric Liub91e0812018-10-02 10:29:00 +000012#include "clang/AST/Decl.h"
Ilya Biryukov98397552018-12-05 17:38:39 +000013#include "clang/AST/DeclBase.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000014#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000015#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000016#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000017#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000018#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000019#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000020#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000021#include "clang/Lex/MacroInfo.h"
22#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Overload.h"
26#include "clang/Sema/Scope.h"
27#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000028#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000029#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000030#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000031#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000032#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000033#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000034#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000035#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000036#include "llvm/ADT/iterator_range.h"
37#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000038#include <list>
39#include <map>
40#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000041
42using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000043using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000044
Douglas Gregor3545ff42009-09-21 16:56:56 +000045namespace {
Fangrui Song050229d2018-11-24 00:14:31 +000046/// A container of code-completion results.
47class ResultBuilder {
48public:
49 /// The type of a name-lookup filter, which can be provided to the
50 /// name-lookup routines to specify which declarations should be included in
51 /// the result set (when it returns true) and which declarations should be
52 /// filtered out (returns false).
53 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000054
Fangrui Song050229d2018-11-24 00:14:31 +000055 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000056
Fangrui Song050229d2018-11-24 00:14:31 +000057private:
58 /// The actual results we have found.
59 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000060
Fangrui Song050229d2018-11-24 00:14:31 +000061 /// A record of all of the declarations we have found and placed
62 /// into the result set, used to ensure that no declaration ever gets into
63 /// the result set twice.
64 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000065
Fangrui Song050229d2018-11-24 00:14:31 +000066 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000067
Fangrui Song050229d2018-11-24 00:14:31 +000068 /// An entry in the shadow map, which is optimized to store
69 /// a single (declaration, index) mapping (the common case) but
70 /// can also store a list of (declaration, index) mappings.
71 class ShadowMapEntry {
72 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000073
Fangrui Song050229d2018-11-24 00:14:31 +000074 /// Contains either the solitary NamedDecl * or a vector
75 /// of (declaration, index) pairs.
76 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000077
Fangrui Song050229d2018-11-24 00:14:31 +000078 /// When the entry contains a single declaration, this is
79 /// the index associated with that entry.
80 unsigned SingleDeclIndex;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000081
Douglas Gregor3545ff42009-09-21 16:56:56 +000082 public:
Fangrui Song050229d2018-11-24 00:14:31 +000083 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000084
Fangrui Song050229d2018-11-24 00:14:31 +000085 void Add(const NamedDecl *ND, unsigned Index) {
86 if (DeclOrVector.isNull()) {
87 // 0 - > 1 elements: just set the single element information.
88 DeclOrVector = ND;
89 SingleDeclIndex = Index;
90 return;
91 }
92
93 if (const NamedDecl *PrevND =
94 DeclOrVector.dyn_cast<const NamedDecl *>()) {
95 // 1 -> 2 elements: create the vector of results and push in the
96 // existing declaration.
97 DeclIndexPairVector *Vec = new DeclIndexPairVector;
98 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
99 DeclOrVector = Vec;
100 }
101
102 // Add the new element to the end of the vector.
103 DeclOrVector.get<DeclIndexPairVector *>()->push_back(
104 DeclIndexPair(ND, Index));
105 }
106
107 void Destroy() {
108 if (DeclIndexPairVector *Vec =
109 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
110 delete Vec;
111 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05fcf842010-11-02 20:36:02 +0000112 }
113 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000114
Fangrui Song050229d2018-11-24 00:14:31 +0000115 // Iteration.
116 class iterator;
117 iterator begin() const;
118 iterator end() const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000119 };
Fangrui Song050229d2018-11-24 00:14:31 +0000120
121 /// A mapping from declaration names to the declarations that have
122 /// this name within a particular scope and their index within the list of
123 /// results.
124 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
125
126 /// The semantic analysis object for which results are being
127 /// produced.
128 Sema &SemaRef;
129
130 /// The allocator used to allocate new code-completion strings.
131 CodeCompletionAllocator &Allocator;
132
133 CodeCompletionTUInfo &CCTUInfo;
134
135 /// If non-NULL, a filter function used to remove any code-completion
136 /// results that are not desirable.
137 LookupFilter Filter;
138
139 /// Whether we should allow declarations as
140 /// nested-name-specifiers that would otherwise be filtered out.
141 bool AllowNestedNameSpecifiers;
142
143 /// If set, the type that we would prefer our resulting value
144 /// declarations to have.
145 ///
146 /// Closely matching the preferred type gives a boost to a result's
147 /// priority.
148 CanQualType PreferredType;
149
150 /// A list of shadow maps, which is used to model name hiding at
151 /// different levels of, e.g., the inheritance hierarchy.
152 std::list<ShadowMap> ShadowMaps;
153
154 /// If we're potentially referring to a C++ member function, the set
155 /// of qualifiers applied to the object type.
156 Qualifiers ObjectTypeQualifiers;
157
158 /// Whether the \p ObjectTypeQualifiers field is active.
159 bool HasObjectTypeQualifiers;
160
161 /// The selector that we prefer.
162 Selector PreferredSelector;
163
164 /// The completion context in which we are gathering results.
165 CodeCompletionContext CompletionContext;
166
167 /// If we are in an instance method definition, the \@implementation
168 /// object.
169 ObjCImplementationDecl *ObjCImplementation;
170
171 void AdjustResultPriorityForDecl(Result &R);
172
173 void MaybeAddConstructorResults(Result R);
174
175public:
176 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
177 CodeCompletionTUInfo &CCTUInfo,
178 const CodeCompletionContext &CompletionContext,
179 LookupFilter Filter = nullptr)
180 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
181 Filter(Filter), AllowNestedNameSpecifiers(false),
182 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
183 ObjCImplementation(nullptr) {
184 // If this is an Objective-C instance method definition, dig out the
185 // corresponding implementation.
186 switch (CompletionContext.getKind()) {
187 case CodeCompletionContext::CCC_Expression:
188 case CodeCompletionContext::CCC_ObjCMessageReceiver:
189 case CodeCompletionContext::CCC_ParenthesizedExpression:
190 case CodeCompletionContext::CCC_Statement:
191 case CodeCompletionContext::CCC_Recovery:
192 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
193 if (Method->isInstanceMethod())
194 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
195 ObjCImplementation = Interface->getImplementation();
196 break;
197
198 default:
199 break;
200 }
201 }
202
203 /// Determine the priority for a reference to the given declaration.
204 unsigned getBasePriority(const NamedDecl *D);
205
206 /// Whether we should include code patterns in the completion
207 /// results.
208 bool includeCodePatterns() const {
209 return SemaRef.CodeCompleter &&
210 SemaRef.CodeCompleter->includeCodePatterns();
211 }
212
213 /// Set the filter used for code-completion results.
214 void setFilter(LookupFilter Filter) { this->Filter = Filter; }
215
216 Result *data() { return Results.empty() ? nullptr : &Results.front(); }
217 unsigned size() const { return Results.size(); }
218 bool empty() const { return Results.empty(); }
219
220 /// Specify the preferred type.
221 void setPreferredType(QualType T) {
222 PreferredType = SemaRef.Context.getCanonicalType(T);
223 }
224
225 /// Set the cv-qualifiers on the object type, for us in filtering
226 /// calls to member functions.
227 ///
228 /// When there are qualifiers in this set, they will be used to filter
229 /// out member functions that aren't available (because there will be a
230 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
231 /// match.
232 void setObjectTypeQualifiers(Qualifiers Quals) {
233 ObjectTypeQualifiers = Quals;
234 HasObjectTypeQualifiers = true;
235 }
236
237 /// Set the preferred selector.
238 ///
239 /// When an Objective-C method declaration result is added, and that
240 /// method's selector matches this preferred selector, we give that method
241 /// a slight priority boost.
242 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
243
244 /// Retrieve the code-completion context for which results are
245 /// being collected.
246 const CodeCompletionContext &getCompletionContext() const {
247 return CompletionContext;
248 }
249
250 /// Specify whether nested-name-specifiers are allowed.
251 void allowNestedNameSpecifiers(bool Allow = true) {
252 AllowNestedNameSpecifiers = Allow;
253 }
254
255 /// Return the semantic analysis object for which we are collecting
256 /// code completion results.
257 Sema &getSema() const { return SemaRef; }
258
259 /// Retrieve the allocator used to allocate code completion strings.
260 CodeCompletionAllocator &getAllocator() const { return Allocator; }
261
262 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
263
264 /// Determine whether the given declaration is at all interesting
265 /// as a code-completion result.
266 ///
267 /// \param ND the declaration that we are inspecting.
268 ///
269 /// \param AsNestedNameSpecifier will be set true if this declaration is
270 /// only interesting when it is a nested-name-specifier.
271 bool isInterestingDecl(const NamedDecl *ND,
272 bool &AsNestedNameSpecifier) const;
273
274 /// Check whether the result is hidden by the Hiding declaration.
275 ///
276 /// \returns true if the result is hidden and cannot be found, false if
277 /// the hidden result could still be found. When false, \p R may be
278 /// modified to describe how the result can be found (e.g., via extra
279 /// qualification).
280 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
281 const NamedDecl *Hiding);
282
283 /// Add a new result to this result set (if it isn't already in one
284 /// of the shadow maps), or replace an existing result (for, e.g., a
285 /// redeclaration).
286 ///
287 /// \param R the result to add (if it is unique).
288 ///
289 /// \param CurContext the context in which this result will be named.
290 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
291
292 /// Add a new result to this result set, where we already know
293 /// the hiding declaration (if any).
294 ///
295 /// \param R the result to add (if it is unique).
296 ///
297 /// \param CurContext the context in which this result will be named.
298 ///
299 /// \param Hiding the declaration that hides the result.
300 ///
301 /// \param InBaseClass whether the result was found in a base
302 /// class of the searched context.
303 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
304 bool InBaseClass);
305
306 /// Add a new non-declaration result to this result set.
307 void AddResult(Result R);
308
309 /// Enter into a new scope.
310 void EnterNewScope();
311
312 /// Exit from the current scope.
313 void ExitScope();
314
315 /// Ignore this declaration, if it is seen again.
316 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
317
318 /// Add a visited context.
319 void addVisitedContext(DeclContext *Ctx) {
320 CompletionContext.addVisitedContext(Ctx);
321 }
322
323 /// \name Name lookup predicates
324 ///
325 /// These predicates can be passed to the name lookup functions to filter the
326 /// results of name lookup. All of the predicates have the same type, so that
327 ///
328 //@{
329 bool IsOrdinaryName(const NamedDecl *ND) const;
330 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
331 bool IsIntegralConstantValue(const NamedDecl *ND) const;
332 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
333 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
334 bool IsEnum(const NamedDecl *ND) const;
335 bool IsClassOrStruct(const NamedDecl *ND) const;
336 bool IsUnion(const NamedDecl *ND) const;
337 bool IsNamespace(const NamedDecl *ND) const;
338 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
339 bool IsType(const NamedDecl *ND) const;
340 bool IsMember(const NamedDecl *ND) const;
341 bool IsObjCIvar(const NamedDecl *ND) const;
342 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
343 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
344 bool IsObjCCollection(const NamedDecl *ND) const;
345 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
346 //@}
347};
348} // namespace
Douglas Gregor3545ff42009-09-21 16:56:56 +0000349
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000350class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000351 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000352 unsigned SingleDeclIndex;
353
354public:
355 typedef DeclIndexPair value_type;
356 typedef value_type reference;
357 typedef std::ptrdiff_t difference_type;
358 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000359
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000360 class pointer {
361 DeclIndexPair Value;
362
363 public:
Fangrui Song050229d2018-11-24 00:14:31 +0000364 pointer(const DeclIndexPair &Value) : Value(Value) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000365
Fangrui Song050229d2018-11-24 00:14:31 +0000366 const DeclIndexPair *operator->() const { return &Value; }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000367 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000368
369 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000370
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000371 iterator(const NamedDecl *SingleDecl, unsigned Index)
Fangrui Song050229d2018-11-24 00:14:31 +0000372 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000373
374 iterator(const DeclIndexPair *Iterator)
Fangrui Song050229d2018-11-24 00:14:31 +0000375 : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000376
377 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000378 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000379 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000380 SingleDeclIndex = 0;
381 return *this;
382 }
383
Fangrui Song050229d2018-11-24 00:14:31 +0000384 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000385 ++I;
386 DeclOrIterator = I;
387 return *this;
388 }
389
Chris Lattner9795b392010-09-04 18:12:20 +0000390 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000391 iterator tmp(*this);
392 ++(*this);
393 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000394 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000395
396 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000397 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000398 return reference(ND, SingleDeclIndex);
399
Fangrui Song050229d2018-11-24 00:14:31 +0000400 return *DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000401 }
402
Fangrui Song050229d2018-11-24 00:14:31 +0000403 pointer operator->() const { return pointer(**this); }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000404
405 friend bool operator==(const iterator &X, const iterator &Y) {
Fangrui Song050229d2018-11-24 00:14:31 +0000406 return X.DeclOrIterator.getOpaqueValue() ==
407 Y.DeclOrIterator.getOpaqueValue() &&
408 X.SingleDeclIndex == Y.SingleDeclIndex;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000409 }
410
411 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000412 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000413 }
414};
415
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000416ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000417ResultBuilder::ShadowMapEntry::begin() const {
418 if (DeclOrVector.isNull())
419 return iterator();
420
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000421 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000422 return iterator(ND, SingleDeclIndex);
423
424 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
425}
426
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000427ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000428ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000429 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000430 return iterator();
431
432 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
433}
434
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000435/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000436/// (\p CurContext) to the target context (\p TargetContext).
437///
438/// \param Context the AST context in which the qualification will be used.
439///
440/// \param CurContext the context where an entity is being named, which is
441/// typically based on the current scope.
442///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000443/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000444/// resides.
445///
446/// \returns a nested name specifier that refers into the target context, or
447/// NULL if no qualification is needed.
448static NestedNameSpecifier *
Fangrui Song050229d2018-11-24 00:14:31 +0000449getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000450 const DeclContext *TargetContext) {
451 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000452
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000453 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000454 CommonAncestor && !CommonAncestor->Encloses(CurContext);
455 CommonAncestor = CommonAncestor->getLookupParent()) {
456 if (CommonAncestor->isTransparentContext() ||
457 CommonAncestor->isFunctionOrMethod())
458 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000459
Douglas Gregor2af2f672009-09-21 20:12:40 +0000460 TargetParents.push_back(CommonAncestor);
461 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000462
463 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000464 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000465 const DeclContext *Parent = TargetParents.pop_back_val();
466
Fangrui Song050229d2018-11-24 00:14:31 +0000467 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000468 if (!Namespace->getIdentifier())
469 continue;
470
Douglas Gregor2af2f672009-09-21 20:12:40 +0000471 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Fangrui Song050229d2018-11-24 00:14:31 +0000472 } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
473 Result = NestedNameSpecifier::Create(
474 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000475 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000476 return Result;
477}
478
Alp Toker034bbd52014-06-30 01:33:53 +0000479/// Determine whether \p Id is a name reserved for the implementation (C99
480/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000481static bool isReservedName(const IdentifierInfo *Id,
482 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000483 if (Id->getLength() < 2)
484 return false;
485 const char *Name = Id->getNameStart();
486 return Name[0] == '_' &&
Fangrui Song050229d2018-11-24 00:14:31 +0000487 (Name[1] == '_' ||
488 (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000489}
490
491// Some declarations have reserved names that we don't want to ever show.
492// Filter out names reserved for the implementation if they come from a
493// system header.
494static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
495 const IdentifierInfo *Id = ND->getIdentifier();
496 if (!Id)
497 return false;
498
499 // Ignore reserved names for compiler provided decls.
500 if (isReservedName(Id) && ND->getLocation().isInvalid())
501 return true;
502
503 // For system headers ignore only double-underscore names.
504 // This allows for system headers providing private symbols with a single
505 // underscore.
506 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000507 SemaRef.SourceMgr.isInSystemHeader(
508 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
509 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000510
511 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000512}
513
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000514bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000515 bool &AsNestedNameSpecifier) const {
516 AsNestedNameSpecifier = false;
517
Richard Smithf2005d32015-12-29 23:34:32 +0000518 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000519 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000520
521 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000522 if (!ND->getDeclName())
523 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000524
Douglas Gregor3545ff42009-09-21 16:56:56 +0000525 // Friend declarations and declarations introduced due to friends are never
526 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000527 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000528 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000529
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000530 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000531 if (isa<ClassTemplateSpecializationDecl>(ND) ||
532 isa<ClassTemplatePartialSpecializationDecl>(ND))
533 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000534
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000535 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000536 if (isa<UsingDecl>(ND))
537 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000538
539 if (shouldIgnoreDueToReservedName(ND, SemaRef))
540 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000541
Douglas Gregor59cab552010-08-16 23:05:20 +0000542 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000543 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
544 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000545 AsNestedNameSpecifier = true;
546
Douglas Gregor3545ff42009-09-21 16:56:56 +0000547 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000548 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000549 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000550 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000551 IsNestedNameSpecifier(ND) &&
552 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000553 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000554 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
555 AsNestedNameSpecifier = true;
556 return true;
557 }
558
Douglas Gregor7c208612010-01-14 00:20:49 +0000559 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000560 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000561 // ... then it must be interesting!
562 return true;
563}
564
Douglas Gregore0717ab2010-01-14 00:41:07 +0000565bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000566 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000567 // In C, there is no way to refer to a hidden name.
568 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
569 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000570 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000571 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000572
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000573 const DeclContext *HiddenCtx =
574 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000575
Douglas Gregore0717ab2010-01-14 00:41:07 +0000576 // There is no way to qualify a name declared in a function or method.
577 if (HiddenCtx->isFunctionOrMethod())
578 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000579
Sebastian Redl50c68252010-08-31 00:36:30 +0000580 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000581 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000582
Douglas Gregore0717ab2010-01-14 00:41:07 +0000583 // We can refer to the result with the appropriate qualification. Do it.
584 R.Hidden = true;
585 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000586
Douglas Gregore0717ab2010-01-14 00:41:07 +0000587 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000588 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000589 R.Declaration->getDeclContext());
590 return false;
591}
592
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000593/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000594/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000595SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000596 switch (T->getTypeClass()) {
597 case Type::Builtin:
598 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000599 case BuiltinType::Void:
600 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000601
Fangrui Song050229d2018-11-24 00:14:31 +0000602 case BuiltinType::NullPtr:
603 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000604
Fangrui Song050229d2018-11-24 00:14:31 +0000605 case BuiltinType::Overload:
606 case BuiltinType::Dependent:
607 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000608
Fangrui Song050229d2018-11-24 00:14:31 +0000609 case BuiltinType::ObjCId:
610 case BuiltinType::ObjCClass:
611 case BuiltinType::ObjCSel:
612 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000613
Fangrui Song050229d2018-11-24 00:14:31 +0000614 default:
615 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000616 }
David Blaikie8a40f702012-01-17 06:56:22 +0000617
Douglas Gregor95887f92010-07-08 23:20:03 +0000618 case Type::Complex:
619 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000620
Douglas Gregor95887f92010-07-08 23:20:03 +0000621 case Type::Pointer:
622 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000623
Douglas Gregor95887f92010-07-08 23:20:03 +0000624 case Type::BlockPointer:
625 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000626
Douglas Gregor95887f92010-07-08 23:20:03 +0000627 case Type::LValueReference:
628 case Type::RValueReference:
629 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000630
Douglas Gregor95887f92010-07-08 23:20:03 +0000631 case Type::ConstantArray:
632 case Type::IncompleteArray:
633 case Type::VariableArray:
634 case Type::DependentSizedArray:
635 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000636
Douglas Gregor95887f92010-07-08 23:20:03 +0000637 case Type::DependentSizedExtVector:
638 case Type::Vector:
639 case Type::ExtVector:
640 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000641
Douglas Gregor95887f92010-07-08 23:20:03 +0000642 case Type::FunctionProto:
643 case Type::FunctionNoProto:
644 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000645
Douglas Gregor95887f92010-07-08 23:20:03 +0000646 case Type::Record:
647 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000648
Douglas Gregor95887f92010-07-08 23:20:03 +0000649 case Type::Enum:
650 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000651
Douglas Gregor95887f92010-07-08 23:20:03 +0000652 case Type::ObjCObject:
653 case Type::ObjCInterface:
654 case Type::ObjCObjectPointer:
655 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000656
Douglas Gregor95887f92010-07-08 23:20:03 +0000657 default:
658 return STC_Other;
659 }
660}
661
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000662/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000663/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000664QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000665 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000666
Fangrui Song050229d2018-11-24 00:14:31 +0000667 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000668 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000669 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000670 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000671
Douglas Gregor95887f92010-07-08 23:20:03 +0000672 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000673 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000674 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000675 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000676 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000677 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000678 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000679 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000680 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000681 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000682 T = Value->getType();
683 else
684 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000685
686 // Dig through references, function pointers, and block pointers to
687 // get down to the likely type of an expression when the entity is
688 // used.
689 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000690 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000691 T = Ref->getPointeeType();
692 continue;
693 }
694
Fangrui Song050229d2018-11-24 00:14:31 +0000695 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000696 if (Pointer->getPointeeType()->isFunctionType()) {
697 T = Pointer->getPointeeType();
698 continue;
699 }
700
701 break;
702 }
703
Fangrui Song050229d2018-11-24 00:14:31 +0000704 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000705 T = Block->getPointeeType();
706 continue;
707 }
708
Fangrui Song050229d2018-11-24 00:14:31 +0000709 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000710 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000711 continue;
712 }
713
714 break;
715 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000716
Douglas Gregoraf670a82011-04-14 20:33:34 +0000717 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000718}
719
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000720unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
721 if (!ND)
722 return CCP_Unlikely;
723
724 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000725 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
726 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000727 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000728 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000729 if (ImplicitParam->getIdentifier() &&
730 ImplicitParam->getIdentifier()->isStr("_cmd"))
731 return CCP_ObjC_cmd;
732
733 return CCP_LocalDeclaration;
734 }
Richard Smith541b38b2013-09-20 01:15:31 +0000735
736 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000737 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
738 // Explicit destructor calls are very rare.
739 if (isa<CXXDestructorDecl>(ND))
740 return CCP_Unlikely;
741 // Explicit operator and conversion function calls are also very rare.
742 auto DeclNameKind = ND->getDeclName().getNameKind();
743 if (DeclNameKind == DeclarationName::CXXOperatorName ||
744 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
745 DeclNameKind == DeclarationName::CXXConversionFunctionName)
746 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000747 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000748 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000749
750 // Content-based decisions.
751 if (isa<EnumConstantDecl>(ND))
752 return CCP_Constant;
753
Douglas Gregor52e0de42013-01-31 05:03:46 +0000754 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
755 // message receiver, or parenthesized expression context. There, it's as
756 // likely that the user will want to write a type as other declarations.
757 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
758 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000759 CompletionContext.getKind() ==
760 CodeCompletionContext::CCC_ObjCMessageReceiver ||
761 CompletionContext.getKind() ==
762 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000763 return CCP_Type;
764
765 return CCP_Declaration;
766}
767
Douglas Gregor50832e02010-09-20 22:39:41 +0000768void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
769 // If this is an Objective-C method declaration whose selector matches our
770 // preferred selector, give it a priority boost.
771 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000772 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000773 if (PreferredSelector == Method->getSelector())
774 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000775
Douglas Gregor50832e02010-09-20 22:39:41 +0000776 // If we have a preferred type, adjust the priority for results with exactly-
777 // matching or nearly-matching types.
778 if (!PreferredType.isNull()) {
779 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
780 if (!T.isNull()) {
781 CanQualType TC = SemaRef.Context.getCanonicalType(T);
782 // Check for exactly-matching types (modulo qualifiers).
783 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
784 R.Priority /= CCF_ExactTypeMatch;
785 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +0000786 else if ((getSimplifiedTypeClass(PreferredType) ==
787 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000788 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000789 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000790 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000791 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000792}
793
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +0000794DeclContext::lookup_result getConstructors(ASTContext &Context,
795 const CXXRecordDecl *Record) {
796 QualType RecordTy = Context.getTypeDeclType(Record);
797 DeclarationName ConstructorName =
798 Context.DeclarationNames.getCXXConstructorName(
799 Context.getCanonicalType(RecordTy));
800 return Record->lookup(ConstructorName);
801}
802
Douglas Gregor0212fd72010-09-21 16:06:22 +0000803void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000804 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000805 !CompletionContext.wantConstructorResults())
806 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000807
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000808 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000809 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000810 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000811 Record = ClassTemplate->getTemplatedDecl();
812 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
813 // Skip specializations and partial specializations.
814 if (isa<ClassTemplateSpecializationDecl>(Record))
815 return;
816 } else {
817 // There are no constructors here.
818 return;
819 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000820
Douglas Gregor0212fd72010-09-21 16:06:22 +0000821 Record = Record->getDefinition();
822 if (!Record)
823 return;
824
Fangrui Song050229d2018-11-24 00:14:31 +0000825 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +0000826 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000827 R.CursorKind = getCursorKindForDecl(R.Declaration);
828 Results.push_back(R);
829 }
830}
831
Sam McCall63c59722018-01-22 20:44:47 +0000832static bool isConstructor(const Decl *ND) {
833 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
834 ND = Tmpl->getTemplatedDecl();
835 return isa<CXXConstructorDecl>(ND);
836}
837
Douglas Gregor7c208612010-01-14 00:20:49 +0000838void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
839 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000840
Douglas Gregor7c208612010-01-14 00:20:49 +0000841 if (R.Kind != Result::RK_Declaration) {
842 // For non-declaration results, just add the result.
843 Results.push_back(R);
844 return;
845 }
846
847 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000848 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
849 CodeCompletionResult Result(Using->getTargetDecl(),
850 getBasePriority(Using->getTargetDecl()),
851 R.Qualifier);
852 Result.ShadowDecl = Using;
853 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000854 return;
855 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000856
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000857 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000858 unsigned IDNS = CanonDecl->getIdentifierNamespace();
859
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000860 bool AsNestedNameSpecifier = false;
861 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000862 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000863
Douglas Gregor0212fd72010-09-21 16:06:22 +0000864 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000865 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000866 return;
867
Douglas Gregor3545ff42009-09-21 16:56:56 +0000868 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000869 ShadowMapEntry::iterator I, IEnd;
870 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
871 if (NamePos != SMap.end()) {
872 I = NamePos->second.begin();
873 IEnd = NamePos->second.end();
874 }
875
876 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000877 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000878 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000879 if (ND->getCanonicalDecl() == CanonDecl) {
880 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000881 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000882
Douglas Gregor3545ff42009-09-21 16:56:56 +0000883 // We're done.
884 return;
885 }
886 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000887
Douglas Gregor3545ff42009-09-21 16:56:56 +0000888 // This is a new declaration in this scope. However, check whether this
889 // declaration name is hidden by a similarly-named declaration in an outer
890 // scope.
891 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
892 --SMEnd;
893 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000894 ShadowMapEntry::iterator I, IEnd;
895 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
896 if (NamePos != SM->end()) {
897 I = NamePos->second.begin();
898 IEnd = NamePos->second.end();
899 }
900 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000901 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000902 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000903 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
904 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000905 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000906
Douglas Gregor3545ff42009-09-21 16:56:56 +0000907 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +0000908 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
909 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000910 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000911 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000912
Douglas Gregor3545ff42009-09-21 16:56:56 +0000913 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000914 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000915 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000916
Douglas Gregor3545ff42009-09-21 16:56:56 +0000917 break;
918 }
919 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000920
Douglas Gregor3545ff42009-09-21 16:56:56 +0000921 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000922 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000923 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000924
Douglas Gregore412a5a2009-09-23 22:26:46 +0000925 // If the filter is for nested-name-specifiers, then this result starts a
926 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000927 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000928 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000929 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000930 } else
Fangrui Song050229d2018-11-24 00:14:31 +0000931 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000932
Douglas Gregor5bf52692009-09-22 23:15:58 +0000933 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000934 if (R.QualifierIsInformative && !R.Qualifier &&
935 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000936 const DeclContext *Ctx = R.Declaration->getDeclContext();
937 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +0000938 R.Qualifier =
939 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000940 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +0000941 R.Qualifier = NestedNameSpecifier::Create(
942 SemaRef.Context, nullptr, false,
943 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000944 else
945 R.QualifierIsInformative = false;
946 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000947
Douglas Gregor3545ff42009-09-21 16:56:56 +0000948 // Insert this result into the set of results and into the current shadow
949 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000950 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000951 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000952
Douglas Gregor0212fd72010-09-21 16:06:22 +0000953 if (!AsNestedNameSpecifier)
954 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000955}
956
Eric Liu4a7cd632018-10-24 12:57:27 +0000957static void setInBaseClass(ResultBuilder::Result &R) {
958 R.Priority += CCD_InBaseClass;
959 R.InBaseClass = true;
960}
961
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000962void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000963 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000964 if (R.Kind != Result::RK_Declaration) {
965 // For non-declaration results, just add the result.
966 Results.push_back(R);
967 return;
968 }
969
Douglas Gregorc580c522010-01-14 01:09:38 +0000970 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +0000971 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000972 CodeCompletionResult Result(Using->getTargetDecl(),
973 getBasePriority(Using->getTargetDecl()),
974 R.Qualifier);
975 Result.ShadowDecl = Using;
976 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000977 return;
978 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000979
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000980 bool AsNestedNameSpecifier = false;
981 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000982 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000983
Douglas Gregor0212fd72010-09-21 16:06:22 +0000984 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000985 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000986 return;
987
Douglas Gregorc580c522010-01-14 01:09:38 +0000988 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
989 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000990
Douglas Gregorc580c522010-01-14 01:09:38 +0000991 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000992 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +0000993 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000994
Douglas Gregorc580c522010-01-14 01:09:38 +0000995 // If the filter is for nested-name-specifiers, then this result starts a
996 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000997 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +0000998 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000999 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001000 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1001 InBaseClass &&
1002 isa<CXXRecordDecl>(
1003 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001004 R.QualifierIsInformative = true;
1005
Douglas Gregorc580c522010-01-14 01:09:38 +00001006 // If this result is supposed to have an informative qualifier, add one.
1007 if (R.QualifierIsInformative && !R.Qualifier &&
1008 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001009 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001010 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1011 R.Qualifier =
1012 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1013 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1014 R.Qualifier = NestedNameSpecifier::Create(
1015 SemaRef.Context, nullptr, false,
1016 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001017 else
1018 R.QualifierIsInformative = false;
1019 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001020
Douglas Gregora2db7932010-05-26 22:00:08 +00001021 // Adjust the priority if this result comes from a base class.
1022 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001023 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001024
Douglas Gregor50832e02010-09-20 22:39:41 +00001025 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001026
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001027 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001028 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001029 if (Method->isInstance()) {
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00001030 Qualifiers MethodQuals = Method->getTypeQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001031 if (ObjectTypeQualifiers == MethodQuals)
1032 R.Priority += CCD_ObjectQualifierMatch;
1033 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001034 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001035 // qualifiers.
1036 return;
1037 }
1038 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001039
Douglas Gregorc580c522010-01-14 01:09:38 +00001040 // Insert this result into the set of results.
1041 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001042
Douglas Gregor0212fd72010-09-21 16:06:22 +00001043 if (!AsNestedNameSpecifier)
1044 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001045}
1046
Douglas Gregor78a21012010-01-14 16:01:26 +00001047void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001048 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001049 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001050 Results.push_back(R);
1051}
1052
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001053/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001054void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001055
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001056/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001057void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001058 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00001059 EEnd = ShadowMaps.back().end();
1060 E != EEnd; ++E)
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001061 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001062
Douglas Gregor3545ff42009-09-21 16:56:56 +00001063 ShadowMaps.pop_back();
1064}
1065
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001066/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001067/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001068bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001069 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001070
Richard Smith541b38b2013-09-20 01:15:31 +00001071 // If name lookup finds a local extern declaration, then we are in a
1072 // context where it behaves like an ordinary name.
1073 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001074 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001075 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001076 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001077 if (isa<ObjCIvarDecl>(ND))
1078 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001079 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001080
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001081 return ND->getIdentifierNamespace() & IDNS;
1082}
1083
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001084/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001085/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001086bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001087 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001088 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001089 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001090 // Objective-C interfaces names are not filtered by this method because they
1091 // can be used in a class property expression. We can still filter out
1092 // @class declarations though.
1093 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1094 if (!ID->getDefinition())
1095 return false;
1096 }
1097
Richard Smith541b38b2013-09-20 01:15:31 +00001098 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001099 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001100 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001101 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001102 if (isa<ObjCIvarDecl>(ND))
1103 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001104 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001105
Douglas Gregor70febae2010-05-28 00:49:12 +00001106 return ND->getIdentifierNamespace() & IDNS;
1107}
1108
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001109bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001110 if (!IsOrdinaryNonTypeName(ND))
1111 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001112
Fangrui Song050229d2018-11-24 00:14:31 +00001113 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001114 if (VD->getType()->isIntegralOrEnumerationType())
1115 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001116
Douglas Gregor85b50632010-07-28 21:50:18 +00001117 return false;
1118}
1119
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001120/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001121/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001122bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001123 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001124
Richard Smith541b38b2013-09-20 01:15:31 +00001125 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001126 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001127 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001128
Fangrui Song050229d2018-11-24 00:14:31 +00001129 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1130 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001131}
1132
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001133/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001134/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001135bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001136 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001137 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001138 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001139
Douglas Gregor3545ff42009-09-21 16:56:56 +00001140 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1141}
1142
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001143/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001144bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001145 return isa<EnumDecl>(ND);
1146}
1147
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001148/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001149bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001150 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001151 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001152 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001153
1154 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001155 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1156 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1157 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001158
Douglas Gregor3545ff42009-09-21 16:56:56 +00001159 return false;
1160}
1161
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001162/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001163bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001164 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001165 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001166 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001167
Fangrui Song050229d2018-11-24 00:14:31 +00001168 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001169 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001170
Douglas Gregor3545ff42009-09-21 16:56:56 +00001171 return false;
1172}
1173
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001174/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001175bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001176 return isa<NamespaceDecl>(ND);
1177}
1178
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001179/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001180/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001181bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001182 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001183}
1184
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001185/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001186bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001187 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001188 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001189}
1190
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001191/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001192/// "." or "->". Only value declarations, nested name specifiers, and
1193/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001194bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001195 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001196 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001197 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001198}
1199
Douglas Gregora817a192010-05-27 23:06:34 +00001200static bool isObjCReceiverType(ASTContext &C, QualType T) {
1201 T = C.getCanonicalType(T);
1202 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001203 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001204 case Type::ObjCInterface:
1205 case Type::ObjCObjectPointer:
1206 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001207
Douglas Gregora817a192010-05-27 23:06:34 +00001208 case Type::Builtin:
1209 switch (cast<BuiltinType>(T)->getKind()) {
1210 case BuiltinType::ObjCId:
1211 case BuiltinType::ObjCClass:
1212 case BuiltinType::ObjCSel:
1213 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001214
Douglas Gregora817a192010-05-27 23:06:34 +00001215 default:
1216 break;
1217 }
1218 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001219
Douglas Gregora817a192010-05-27 23:06:34 +00001220 default:
1221 break;
1222 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001223
David Blaikiebbafb8a2012-03-11 07:00:24 +00001224 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001225 return false;
1226
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001227 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001228 // particular class type has any conversions to Objective-C types. For now,
1229 // just accept all class types.
1230 return T->isDependentType() || T->isRecordType();
1231}
1232
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001233bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001234 QualType T = getDeclUsageType(SemaRef.Context, ND);
1235 if (T.isNull())
1236 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001237
Douglas Gregora817a192010-05-27 23:06:34 +00001238 T = SemaRef.Context.getBaseElementType(T);
1239 return isObjCReceiverType(SemaRef.Context, T);
1240}
1241
Fangrui Song050229d2018-11-24 00:14:31 +00001242bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1243 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001244 if (IsObjCMessageReceiver(ND))
1245 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001246
Fangrui Song050229d2018-11-24 00:14:31 +00001247 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001248 if (!Var)
1249 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001250
Douglas Gregord8c61782012-02-15 15:34:24 +00001251 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1252}
1253
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001254bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001255 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1256 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001257 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001258
Douglas Gregor68762e72010-08-23 21:17:50 +00001259 QualType T = getDeclUsageType(SemaRef.Context, ND);
1260 if (T.isNull())
1261 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001262
Douglas Gregor68762e72010-08-23 21:17:50 +00001263 T = SemaRef.Context.getBaseElementType(T);
1264 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001265 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001266 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001267}
Douglas Gregora817a192010-05-27 23:06:34 +00001268
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001269bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001270 return false;
1271}
1272
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001273/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001274/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001275bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001276 return isa<ObjCIvarDecl>(ND);
1277}
1278
Douglas Gregorc580c522010-01-14 01:09:38 +00001279namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001280
Fangrui Song050229d2018-11-24 00:14:31 +00001281/// Visible declaration consumer that adds a code-completion result
1282/// for each visible declaration.
1283class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1284 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001285 DeclContext *InitialLookupCtx;
1286 // NamingClass and BaseType are used for access-checking. See
1287 // Sema::IsSimplyAccessible for details.
1288 CXXRecordDecl *NamingClass;
1289 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001290 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001291
Fangrui Song050229d2018-11-24 00:14:31 +00001292public:
1293 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001294 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1295 QualType BaseType = QualType(),
1296 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1297 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1298 FixIts(std::move(FixIts)) {
1299 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1300 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1301 if (BaseType.isNull()) {
1302 auto ThisType = Results.getSema().getCurrentThisType();
1303 if (!ThisType.isNull()) {
1304 assert(ThisType->isPointerType());
1305 BaseType = ThisType->getPointeeType();
1306 if (!NamingClass)
1307 NamingClass = BaseType->getAsCXXRecordDecl();
1308 }
1309 }
1310 this->BaseType = BaseType;
1311 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001312
Fangrui Song050229d2018-11-24 00:14:31 +00001313 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1314 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001315 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001316 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001317 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001318 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001319
Fangrui Song050229d2018-11-24 00:14:31 +00001320 void EnteredContext(DeclContext *Ctx) override {
1321 Results.addVisitedContext(Ctx);
1322 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001323
1324private:
1325 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1326 // Naming class to use for access check. In most cases it was provided
1327 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1328 // for unqualified lookup we fallback to the \p Ctx in which we found the
1329 // member.
1330 auto *NamingClass = this->NamingClass;
1331 QualType BaseType = this->BaseType;
1332 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1333 if (!NamingClass)
1334 NamingClass = Cls;
1335 // When we emulate implicit 'this->' in an unqualified lookup, we might
1336 // end up with an invalid naming class. In that case, we avoid emulating
1337 // 'this->' qualifier to satisfy preconditions of the access checking.
1338 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1339 !NamingClass->isDerivedFrom(Cls)) {
1340 NamingClass = Cls;
1341 BaseType = QualType();
1342 }
1343 } else {
1344 // The decl was found outside the C++ class, so only ObjC access checks
1345 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1346 // out.
1347 NamingClass = nullptr;
1348 BaseType = QualType();
1349 }
1350 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1351 }
Fangrui Song050229d2018-11-24 00:14:31 +00001352};
1353} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001354
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001355/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001356static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001357 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001358 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001359 Results.AddResult(Result("short", CCP_Type));
1360 Results.AddResult(Result("long", CCP_Type));
1361 Results.AddResult(Result("signed", CCP_Type));
1362 Results.AddResult(Result("unsigned", CCP_Type));
1363 Results.AddResult(Result("void", CCP_Type));
1364 Results.AddResult(Result("char", CCP_Type));
1365 Results.AddResult(Result("int", CCP_Type));
1366 Results.AddResult(Result("float", CCP_Type));
1367 Results.AddResult(Result("double", CCP_Type));
1368 Results.AddResult(Result("enum", CCP_Type));
1369 Results.AddResult(Result("struct", CCP_Type));
1370 Results.AddResult(Result("union", CCP_Type));
1371 Results.AddResult(Result("const", CCP_Type));
1372 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001373
Douglas Gregor3545ff42009-09-21 16:56:56 +00001374 if (LangOpts.C99) {
1375 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001376 Results.AddResult(Result("_Complex", CCP_Type));
1377 Results.AddResult(Result("_Imaginary", CCP_Type));
1378 Results.AddResult(Result("_Bool", CCP_Type));
1379 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001380 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001381
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001382 CodeCompletionBuilder Builder(Results.getAllocator(),
1383 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001384 if (LangOpts.CPlusPlus) {
1385 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001386 Results.AddResult(
1387 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001388 Results.AddResult(Result("class", CCP_Type));
1389 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001390
Douglas Gregorf4c33342010-05-28 00:22:41 +00001391 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001392 Builder.AddTypedTextChunk("typename");
1393 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1394 Builder.AddPlaceholderChunk("qualifier");
1395 Builder.AddTextChunk("::");
1396 Builder.AddPlaceholderChunk("name");
1397 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001398
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001399 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001400 Results.AddResult(Result("auto", CCP_Type));
1401 Results.AddResult(Result("char16_t", CCP_Type));
1402 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001403
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001404 Builder.AddTypedTextChunk("decltype");
1405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1406 Builder.AddPlaceholderChunk("expression");
1407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1408 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001409 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001410 } else
1411 Results.AddResult(Result("__auto_type", CCP_Type));
1412
Richard Smith7b301e22018-05-24 21:51:52 +00001413 // GNU keywords
1414 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001415 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001416 // Results.AddResult(Result("_Decimal32"));
1417 // Results.AddResult(Result("_Decimal64"));
1418 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001419
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001420 Builder.AddTypedTextChunk("typeof");
1421 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1422 Builder.AddPlaceholderChunk("expression");
1423 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001424
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001425 Builder.AddTypedTextChunk("typeof");
1426 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1427 Builder.AddPlaceholderChunk("type");
1428 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1429 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001430 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001431
1432 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001433 Results.AddResult(Result("_Nonnull", CCP_Type));
1434 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1435 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001436}
1437
John McCallfaf5fb42010-08-26 23:41:50 +00001438static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001439 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001440 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001441 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001442 // Note: we don't suggest either "auto" or "register", because both
1443 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1444 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001445 Results.AddResult(Result("extern"));
1446 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001447
1448 if (LangOpts.CPlusPlus11) {
1449 CodeCompletionAllocator &Allocator = Results.getAllocator();
1450 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1451
1452 // alignas
1453 Builder.AddTypedTextChunk("alignas");
1454 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1455 Builder.AddPlaceholderChunk("expression");
1456 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1457 Results.AddResult(Result(Builder.TakeString()));
1458
1459 Results.AddResult(Result("constexpr"));
1460 Results.AddResult(Result("thread_local"));
1461 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001462}
1463
John McCallfaf5fb42010-08-26 23:41:50 +00001464static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001465 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001466 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001467 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001468 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001469 case Sema::PCC_Class:
1470 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001471 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001472 Results.AddResult(Result("explicit"));
1473 Results.AddResult(Result("friend"));
1474 Results.AddResult(Result("mutable"));
1475 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001476 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001477 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001478
John McCallfaf5fb42010-08-26 23:41:50 +00001479 case Sema::PCC_ObjCInterface:
1480 case Sema::PCC_ObjCImplementation:
1481 case Sema::PCC_Namespace:
1482 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001483 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001484 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001485 break;
1486
John McCallfaf5fb42010-08-26 23:41:50 +00001487 case Sema::PCC_ObjCInstanceVariableList:
1488 case Sema::PCC_Expression:
1489 case Sema::PCC_Statement:
1490 case Sema::PCC_ForInit:
1491 case Sema::PCC_Condition:
1492 case Sema::PCC_RecoveryInFunction:
1493 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001494 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001495 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001496 break;
1497 }
1498}
1499
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001500static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1501static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1502static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001503 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001504static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001505 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001506static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001507 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001508static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001509
Douglas Gregorf4c33342010-05-28 00:22:41 +00001510static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001511 CodeCompletionBuilder Builder(Results.getAllocator(),
1512 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001513 Builder.AddTypedTextChunk("typedef");
1514 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1515 Builder.AddPlaceholderChunk("type");
1516 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1517 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001518 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001519}
1520
John McCallfaf5fb42010-08-26 23:41:50 +00001521static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001522 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001523 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001524 case Sema::PCC_Namespace:
1525 case Sema::PCC_Class:
1526 case Sema::PCC_ObjCInstanceVariableList:
1527 case Sema::PCC_Template:
1528 case Sema::PCC_MemberTemplate:
1529 case Sema::PCC_Statement:
1530 case Sema::PCC_RecoveryInFunction:
1531 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001532 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001533 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001534 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001535
John McCallfaf5fb42010-08-26 23:41:50 +00001536 case Sema::PCC_Expression:
1537 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001538 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001539
Douglas Gregor5e35d592010-09-14 23:59:36 +00001540 case Sema::PCC_ObjCInterface:
1541 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001542 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001543
John McCallfaf5fb42010-08-26 23:41:50 +00001544 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001545 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001546 }
David Blaikie8a40f702012-01-17 06:56:22 +00001547
1548 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001549}
1550
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001551static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1552 const Preprocessor &PP) {
1553 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001554 Policy.AnonymousTagLocations = false;
1555 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001556 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001557 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001558 return Policy;
1559}
1560
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001561/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001562static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1563 return getCompletionPrintingPolicy(S.Context, S.PP);
1564}
1565
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001566/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001567/// that has the appropriate lifetime for code completion.
1568///
1569/// This routine provides a fast path where we provide constant strings for
1570/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001571static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001572 const PrintingPolicy &Policy,
1573 CodeCompletionAllocator &Allocator) {
1574 if (!T.getLocalQualifiers()) {
1575 // Built-in type names are constant strings.
1576 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001577 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001578
Douglas Gregore5c79d52011-10-18 21:20:17 +00001579 // Anonymous tag types are constant strings.
1580 if (const TagType *TagT = dyn_cast<TagType>(T))
1581 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001582 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001583 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001584 case TTK_Struct:
1585 return "struct <anonymous>";
1586 case TTK_Interface:
1587 return "__interface <anonymous>";
1588 case TTK_Class:
1589 return "class <anonymous>";
1590 case TTK_Union:
1591 return "union <anonymous>";
1592 case TTK_Enum:
1593 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001594 }
1595 }
1596 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001597
Douglas Gregore5c79d52011-10-18 21:20:17 +00001598 // Slow path: format the type as a string.
1599 std::string Result;
1600 T.getAsStringInternal(Result, Policy);
1601 return Allocator.CopyString(Result);
1602}
1603
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001604/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001605static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1606 QualType ThisTy = S.getCurrentThisType();
1607 if (ThisTy.isNull())
1608 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001609
Douglas Gregord8c61782012-02-15 15:34:24 +00001610 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001611 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001612 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001613 Builder.AddResultTypeChunk(
1614 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001615 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001616 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001617}
1618
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001619static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1620 ResultBuilder &Results,
1621 const LangOptions &LangOpts) {
1622 if (!LangOpts.CPlusPlus11)
1623 return;
1624
1625 Builder.AddTypedTextChunk("static_assert");
1626 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1627 Builder.AddPlaceholderChunk("expression");
1628 Builder.AddChunk(CodeCompletionString::CK_Comma);
1629 Builder.AddPlaceholderChunk("message");
1630 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1631 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1632}
1633
Fangrui Song050229d2018-11-24 00:14:31 +00001634static void printOverrideString(llvm::raw_ostream &OS,
1635 CodeCompletionString *CCS) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001636 for (const auto &C : *CCS) {
1637 if (C.Kind == CodeCompletionString::CK_Optional)
1638 printOverrideString(OS, C.Optional);
1639 else
1640 OS << C.Text;
1641 // Add a space after return type.
1642 if (C.Kind == CodeCompletionString::CK_ResultType)
1643 OS << ' ';
1644 }
1645}
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001646
1647static void AddOverrideResults(ResultBuilder &Results,
1648 const CodeCompletionContext &CCContext,
1649 CodeCompletionBuilder &Builder) {
1650 Sema &S = Results.getSema();
1651 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1652 // If not inside a class/struct/union return empty.
1653 if (!CR)
1654 return;
1655 // First store overrides within current class.
1656 // These are stored by name to make querying fast in the later step.
1657 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1658 for (auto *Method : CR->methods()) {
1659 if (!Method->isVirtual() || !Method->getIdentifier())
1660 continue;
1661 Overrides[Method->getName()].push_back(Method);
1662 }
1663
1664 for (const auto &Base : CR->bases()) {
1665 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1666 if (!BR)
1667 continue;
1668 for (auto *Method : BR->methods()) {
1669 if (!Method->isVirtual() || !Method->getIdentifier())
1670 continue;
1671 const auto it = Overrides.find(Method->getName());
1672 bool IsOverriden = false;
1673 if (it != Overrides.end()) {
1674 for (auto *MD : it->second) {
1675 // If the method in current body is not an overload of this virtual
1676 // function, then it overrides this one.
1677 if (!S.IsOverload(MD, Method, false)) {
1678 IsOverriden = true;
1679 break;
1680 }
1681 }
1682 }
1683 if (!IsOverriden) {
1684 // Generates a new CodeCompletionResult by taking this function and
1685 // converting it into an override declaration with only one chunk in the
1686 // final CodeCompletionString as a TypedTextChunk.
1687 std::string OverrideSignature;
1688 llvm::raw_string_ostream OS(OverrideSignature);
1689 CodeCompletionResult CCR(Method, 0);
1690 PrintingPolicy Policy =
1691 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1692 auto *CCS = CCR.createCodeCompletionStringForOverride(
1693 S.getPreprocessor(), S.getASTContext(), Builder,
1694 /*IncludeBriefComments=*/false, CCContext, Policy);
1695 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1696 }
1697 }
1698 }
1699}
1700
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001701/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001702static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1703 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001704 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001705 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001706
John McCall276321a2010-08-25 06:19:51 +00001707 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001708 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001709 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001710 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001711 if (Results.includeCodePatterns()) {
1712 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001713 Builder.AddTypedTextChunk("namespace");
1714 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1715 Builder.AddPlaceholderChunk("identifier");
1716 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1717 Builder.AddPlaceholderChunk("declarations");
1718 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1719 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1720 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001721 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001722
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001723 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001724 Builder.AddTypedTextChunk("namespace");
1725 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1726 Builder.AddPlaceholderChunk("name");
1727 Builder.AddChunk(CodeCompletionString::CK_Equal);
1728 Builder.AddPlaceholderChunk("namespace");
1729 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001730
1731 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001732 Builder.AddTypedTextChunk("using");
1733 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1734 Builder.AddTextChunk("namespace");
1735 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1736 Builder.AddPlaceholderChunk("identifier");
1737 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001738
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001739 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001740 Builder.AddTypedTextChunk("asm");
1741 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1742 Builder.AddPlaceholderChunk("string-literal");
1743 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1744 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001745
Douglas Gregorf4c33342010-05-28 00:22:41 +00001746 if (Results.includeCodePatterns()) {
1747 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001748 Builder.AddTypedTextChunk("template");
1749 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1750 Builder.AddPlaceholderChunk("declaration");
1751 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001752 } else {
1753 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001754 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001755 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001756
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001757 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001758 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001759
Douglas Gregorf4c33342010-05-28 00:22:41 +00001760 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001761 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001762
John McCallfaf5fb42010-08-26 23:41:50 +00001763 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001764 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001765 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001766 Builder.AddTypedTextChunk("using");
1767 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1768 Builder.AddPlaceholderChunk("qualifier");
1769 Builder.AddTextChunk("::");
1770 Builder.AddPlaceholderChunk("name");
1771 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001772
Douglas Gregorf4c33342010-05-28 00:22:41 +00001773 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001774 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001775 Builder.AddTypedTextChunk("using");
1776 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1777 Builder.AddTextChunk("typename");
1778 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1779 Builder.AddPlaceholderChunk("qualifier");
1780 Builder.AddTextChunk("::");
1781 Builder.AddPlaceholderChunk("name");
1782 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001783 }
1784
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001785 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1786
John McCallfaf5fb42010-08-26 23:41:50 +00001787 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001788 AddTypedefResult(Results);
1789
Erik Verbruggen6524c052017-10-24 13:46:58 +00001790 bool IsNotInheritanceScope =
1791 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001792 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001793 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001794 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001795 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001796 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001797
1798 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001799 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001800 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001801 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001802 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001803
1804 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001805 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001806 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001807 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001808 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001809
1810 // FIXME: This adds override results only if we are at the first word of
1811 // the declaration/definition. Also call this from other sides to have
1812 // more use-cases.
1813 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
1814 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001815 }
1816 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001817 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001818
John McCallfaf5fb42010-08-26 23:41:50 +00001819 case Sema::PCC_Template:
1820 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001821 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001822 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001823 Builder.AddTypedTextChunk("template");
1824 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1825 Builder.AddPlaceholderChunk("parameters");
1826 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1827 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001828 } else {
1829 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001830 }
1831
David Blaikiebbafb8a2012-03-11 07:00:24 +00001832 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1833 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001834 break;
1835
John McCallfaf5fb42010-08-26 23:41:50 +00001836 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001837 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1838 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1839 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001840 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001841
John McCallfaf5fb42010-08-26 23:41:50 +00001842 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001843 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1844 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1845 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001846 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001847
John McCallfaf5fb42010-08-26 23:41:50 +00001848 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001849 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001850 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001851
John McCallfaf5fb42010-08-26 23:41:50 +00001852 case Sema::PCC_RecoveryInFunction:
1853 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001854 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001855
David Blaikiebbafb8a2012-03-11 07:00:24 +00001856 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1857 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001858 Builder.AddTypedTextChunk("try");
1859 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1860 Builder.AddPlaceholderChunk("statements");
1861 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1862 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1863 Builder.AddTextChunk("catch");
1864 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1865 Builder.AddPlaceholderChunk("declaration");
1866 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1867 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1868 Builder.AddPlaceholderChunk("statements");
1869 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1870 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1871 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001872 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001873 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001874 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001875
Douglas Gregorf64acca2010-05-25 21:41:55 +00001876 if (Results.includeCodePatterns()) {
1877 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001878 Builder.AddTypedTextChunk("if");
1879 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001880 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001881 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001882 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001883 Builder.AddPlaceholderChunk("expression");
1884 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1885 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1886 Builder.AddPlaceholderChunk("statements");
1887 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1888 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1889 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001890
Douglas Gregorf64acca2010-05-25 21:41:55 +00001891 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001892 Builder.AddTypedTextChunk("switch");
1893 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001894 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001895 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001896 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001897 Builder.AddPlaceholderChunk("expression");
1898 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1899 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1900 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1901 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1902 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001903 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001904
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001905 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00001906 if (SemaRef.getCurFunction() &&
1907 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001908 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001909 Builder.AddTypedTextChunk("case");
1910 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1911 Builder.AddPlaceholderChunk("expression");
1912 Builder.AddChunk(CodeCompletionString::CK_Colon);
1913 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001914
1915 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001916 Builder.AddTypedTextChunk("default");
1917 Builder.AddChunk(CodeCompletionString::CK_Colon);
1918 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001919 }
1920
Douglas Gregorf64acca2010-05-25 21:41:55 +00001921 if (Results.includeCodePatterns()) {
1922 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001923 Builder.AddTypedTextChunk("while");
1924 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001925 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001926 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001927 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001928 Builder.AddPlaceholderChunk("expression");
1929 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1930 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1931 Builder.AddPlaceholderChunk("statements");
1932 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1933 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1934 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001935
1936 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001937 Builder.AddTypedTextChunk("do");
1938 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1939 Builder.AddPlaceholderChunk("statements");
1940 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1941 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1942 Builder.AddTextChunk("while");
1943 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1944 Builder.AddPlaceholderChunk("expression");
1945 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1946 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001947
Douglas Gregorf64acca2010-05-25 21:41:55 +00001948 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001949 Builder.AddTypedTextChunk("for");
1950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001951 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001952 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001953 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001954 Builder.AddPlaceholderChunk("init-expression");
1955 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1956 Builder.AddPlaceholderChunk("condition");
1957 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1958 Builder.AddPlaceholderChunk("inc-expression");
1959 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1960 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1961 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1962 Builder.AddPlaceholderChunk("statements");
1963 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1964 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1965 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001966 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001967
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001968 if (S->getContinueParent()) {
1969 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001970 Builder.AddTypedTextChunk("continue");
1971 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001972 }
1973
1974 if (S->getBreakParent()) {
1975 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001976 Builder.AddTypedTextChunk("break");
1977 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001978 }
1979
1980 // "return expression ;" or "return ;", depending on whether we
1981 // know the function is void or not.
1982 bool isVoid = false;
Fangrui Song050229d2018-11-24 00:14:31 +00001983 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001984 isVoid = Function->getReturnType()->isVoidType();
Fangrui Song050229d2018-11-24 00:14:31 +00001985 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001986 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001987 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001988 !SemaRef.getCurBlock()->ReturnType.isNull())
1989 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001990 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001991 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001992 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1993 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001994 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001995 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001996
Douglas Gregorf4c33342010-05-28 00:22:41 +00001997 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001998 Builder.AddTypedTextChunk("goto");
1999 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2000 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002001 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002002
Douglas Gregorf4c33342010-05-28 00:22:41 +00002003 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002004 Builder.AddTypedTextChunk("using");
2005 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2006 Builder.AddTextChunk("namespace");
2007 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2008 Builder.AddPlaceholderChunk("identifier");
2009 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002010
2011 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002012 }
Fangrui Song050229d2018-11-24 00:14:31 +00002013 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002014
2015 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002016 case Sema::PCC_ForInit:
2017 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002018 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002019 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002020 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002021
Douglas Gregor5e35d592010-09-14 23:59:36 +00002022 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002023 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002024 CCC == Sema::PCC_ParenthesizedExpression) {
2025 // (__bridge <type>)<expression>
2026 Builder.AddTypedTextChunk("__bridge");
2027 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2028 Builder.AddPlaceholderChunk("type");
2029 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2030 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002031 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002032
2033 // (__bridge_transfer <Objective-C type>)<expression>
2034 Builder.AddTypedTextChunk("__bridge_transfer");
2035 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2036 Builder.AddPlaceholderChunk("Objective-C type");
2037 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2038 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002039 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002040
2041 // (__bridge_retained <CF type>)<expression>
2042 Builder.AddTypedTextChunk("__bridge_retained");
2043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2044 Builder.AddPlaceholderChunk("CF type");
2045 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2046 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002047 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002048 }
2049 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002050 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002051
John McCallfaf5fb42010-08-26 23:41:50 +00002052 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002053 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002054 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002055 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002056
Douglas Gregore5c79d52011-10-18 21:20:17 +00002057 // true
2058 Builder.AddResultTypeChunk("bool");
2059 Builder.AddTypedTextChunk("true");
2060 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002061
Douglas Gregore5c79d52011-10-18 21:20:17 +00002062 // false
2063 Builder.AddResultTypeChunk("bool");
2064 Builder.AddTypedTextChunk("false");
2065 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002066
David Blaikiebbafb8a2012-03-11 07:00:24 +00002067 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002068 // dynamic_cast < type-id > ( expression )
2069 Builder.AddTypedTextChunk("dynamic_cast");
2070 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2071 Builder.AddPlaceholderChunk("type");
2072 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2073 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2074 Builder.AddPlaceholderChunk("expression");
2075 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002076 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002077 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002078
Douglas Gregorf4c33342010-05-28 00:22:41 +00002079 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002080 Builder.AddTypedTextChunk("static_cast");
2081 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2082 Builder.AddPlaceholderChunk("type");
2083 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2084 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2085 Builder.AddPlaceholderChunk("expression");
2086 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002087 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002088
Douglas Gregorf4c33342010-05-28 00:22:41 +00002089 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002090 Builder.AddTypedTextChunk("reinterpret_cast");
2091 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2092 Builder.AddPlaceholderChunk("type");
2093 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2094 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2095 Builder.AddPlaceholderChunk("expression");
2096 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002097 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002098
Douglas Gregorf4c33342010-05-28 00:22:41 +00002099 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002100 Builder.AddTypedTextChunk("const_cast");
2101 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2102 Builder.AddPlaceholderChunk("type");
2103 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2104 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2105 Builder.AddPlaceholderChunk("expression");
2106 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002107 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002108
David Blaikiebbafb8a2012-03-11 07:00:24 +00002109 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002110 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002111 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002112 Builder.AddTypedTextChunk("typeid");
2113 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2114 Builder.AddPlaceholderChunk("expression-or-type");
2115 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002116 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002117 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002118
Douglas Gregorf4c33342010-05-28 00:22:41 +00002119 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002120 Builder.AddTypedTextChunk("new");
2121 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2122 Builder.AddPlaceholderChunk("type");
2123 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2124 Builder.AddPlaceholderChunk("expressions");
2125 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002126 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002127
Douglas Gregorf4c33342010-05-28 00:22:41 +00002128 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002129 Builder.AddTypedTextChunk("new");
2130 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2131 Builder.AddPlaceholderChunk("type");
2132 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2133 Builder.AddPlaceholderChunk("size");
2134 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2135 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2136 Builder.AddPlaceholderChunk("expressions");
2137 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002138 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002139
Douglas Gregorf4c33342010-05-28 00:22:41 +00002140 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002141 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002142 Builder.AddTypedTextChunk("delete");
2143 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2144 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002145 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002146
Douglas Gregorf4c33342010-05-28 00:22:41 +00002147 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002148 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002149 Builder.AddTypedTextChunk("delete");
2150 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2151 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2152 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2154 Builder.AddPlaceholderChunk("expression");
2155 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002156
David Blaikiebbafb8a2012-03-11 07:00:24 +00002157 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002158 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002159 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002160 Builder.AddTypedTextChunk("throw");
2161 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2162 Builder.AddPlaceholderChunk("expression");
2163 Results.AddResult(Result(Builder.TakeString()));
2164 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002165
Douglas Gregora2db7932010-05-26 22:00:08 +00002166 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002167
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002168 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002169 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002170 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002171 Builder.AddTypedTextChunk("nullptr");
2172 Results.AddResult(Result(Builder.TakeString()));
2173
2174 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002175 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002176 Builder.AddTypedTextChunk("alignof");
2177 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2178 Builder.AddPlaceholderChunk("type");
2179 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2180 Results.AddResult(Result(Builder.TakeString()));
2181
2182 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002183 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002184 Builder.AddTypedTextChunk("noexcept");
2185 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2186 Builder.AddPlaceholderChunk("expression");
2187 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2188 Results.AddResult(Result(Builder.TakeString()));
2189
2190 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002191 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002192 Builder.AddTypedTextChunk("sizeof...");
2193 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2194 Builder.AddPlaceholderChunk("parameter-pack");
2195 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2196 Results.AddResult(Result(Builder.TakeString()));
2197 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002198 }
2199
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002200 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002201 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002202 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2203 // The interface can be NULL.
2204 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002205 if (ID->getSuperClass()) {
2206 std::string SuperType;
2207 SuperType = ID->getSuperClass()->getNameAsString();
2208 if (Method->isInstanceMethod())
2209 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002210
Douglas Gregore5c79d52011-10-18 21:20:17 +00002211 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2212 Builder.AddTypedTextChunk("super");
2213 Results.AddResult(Result(Builder.TakeString()));
2214 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002215 }
2216
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002217 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002218 }
2219
Jordan Rose58d54722012-06-30 21:33:57 +00002220 if (SemaRef.getLangOpts().C11) {
2221 // _Alignof
2222 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002223 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002224 Builder.AddTypedTextChunk("alignof");
2225 else
2226 Builder.AddTypedTextChunk("_Alignof");
2227 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2228 Builder.AddPlaceholderChunk("type");
2229 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2230 Results.AddResult(Result(Builder.TakeString()));
2231 }
2232
Douglas Gregorf4c33342010-05-28 00:22:41 +00002233 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002234 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002235 Builder.AddTypedTextChunk("sizeof");
2236 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2237 Builder.AddPlaceholderChunk("expression-or-type");
2238 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2239 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002240 break;
2241 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002242
John McCallfaf5fb42010-08-26 23:41:50 +00002243 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002244 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002245 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002246 }
2247
David Blaikiebbafb8a2012-03-11 07:00:24 +00002248 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2249 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002250
David Blaikiebbafb8a2012-03-11 07:00:24 +00002251 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002252 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002253}
2254
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002255/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002256/// type chunk.
2257static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002258 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002259 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002260 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002261 if (!ND)
2262 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002263
2264 // Skip constructors and conversion functions, which have their return types
2265 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002266 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002267 return;
2268
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002269 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002270 QualType T;
2271 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002272 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002273 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002274 if (!BaseType.isNull())
2275 T = Method->getSendResultType(BaseType);
2276 else
2277 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002278 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002279 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002280 T = clang::TypeName::getFullyQualifiedType(T, Context);
2281 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002282 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002283 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002284 if (!BaseType.isNull())
2285 T = Ivar->getUsageType(BaseType);
2286 else
2287 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002288 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002289 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002290 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002291 if (!BaseType.isNull())
2292 T = Property->getUsageType(BaseType);
2293 else
2294 T = Property->getType();
2295 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002296
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002297 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2298 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002299
Fangrui Song050229d2018-11-24 00:14:31 +00002300 Result.AddResultTypeChunk(
2301 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002302}
2303
Richard Smith20e883e2015-04-29 23:20:19 +00002304static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002305 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002306 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002307 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2308 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002309 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002310 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002311 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002312 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002313 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002314 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002315 }
2316}
2317
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002318static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002319 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002320 std::string Result;
2321 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002322 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002323 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002324 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002325 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002326 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002327 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002328 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002329 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002330 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002331 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002332 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002333 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2334 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2335 switch (*nullability) {
2336 case NullabilityKind::NonNull:
2337 Result += "nonnull ";
2338 break;
2339
2340 case NullabilityKind::Nullable:
2341 Result += "nullable ";
2342 break;
2343
2344 case NullabilityKind::Unspecified:
2345 Result += "null_unspecified ";
2346 break;
2347 }
2348 }
2349 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002350 return Result;
2351}
2352
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002353/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002354/// block placeholder.
2355///
2356/// This function ignores things like typedefs and qualifiers in order to
2357/// present the most relevant and accurate block placeholders in code completion
2358/// results.
2359static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2360 FunctionTypeLoc &Block,
2361 FunctionProtoTypeLoc &BlockProto,
2362 bool SuppressBlock = false) {
2363 if (!TSInfo)
2364 return;
2365 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2366 while (true) {
2367 // Look through typedefs.
2368 if (!SuppressBlock) {
2369 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2370 if (TypeSourceInfo *InnerTSInfo =
2371 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2372 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2373 continue;
2374 }
2375 }
2376
2377 // Look through qualified types
2378 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2379 TL = QualifiedTL.getUnqualifiedLoc();
2380 continue;
2381 }
2382
2383 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2384 TL = AttrTL.getModifiedLoc();
2385 continue;
2386 }
2387 }
2388
2389 // Try to get the function prototype behind the block pointer type,
2390 // then we're done.
2391 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2392 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2393 Block = TL.getAs<FunctionTypeLoc>();
2394 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2395 }
2396 break;
2397 }
2398}
2399
Alex Lorenz920ae142016-10-18 10:38:58 +00002400static std::string
2401formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2402 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002403 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002404 bool SuppressBlock = false,
2405 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2406
Fangrui Song050229d2018-11-24 00:14:31 +00002407static std::string
2408FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2409 bool SuppressName = false, bool SuppressBlock = false,
2410 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002411 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2412 if (Param->getType()->isDependentType() ||
2413 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002414 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002415 // containing that parameter's type.
2416 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002417
Douglas Gregor981a0c42010-08-29 19:47:46 +00002418 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002419 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002420
Douglas Gregor86b42682015-06-19 18:27:52 +00002421 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002422 if (ObjCSubsts)
2423 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2424 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002425 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002426 Result =
2427 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002428 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002429 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002430 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002431 } else {
2432 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002433 }
2434 return Result;
2435 }
Alex Lorenza1951202016-10-18 10:35:27 +00002436
Douglas Gregore90dd002010-08-24 16:15:59 +00002437 // The argument for a block pointer parameter is a block literal with
2438 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002439 FunctionTypeLoc Block;
2440 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002441 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2442 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002443 // Try to retrieve the block type information from the property if this is a
2444 // parameter in a setter.
2445 if (!Block && ObjCMethodParam &&
2446 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2447 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2448 ->findPropertyDecl(/*CheckOverrides=*/false))
2449 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2450 SuppressBlock);
2451 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002452
2453 if (!Block) {
2454 // We were unable to find a FunctionProtoTypeLoc with parameter names
2455 // for the block; just use the parameter type as a placeholder.
2456 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002457 if (!ObjCMethodParam && Param->getIdentifier())
2458 Result = Param->getIdentifier()->getName();
2459
Douglas Gregor86b42682015-06-19 18:27:52 +00002460 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002461
Douglas Gregore90dd002010-08-24 16:15:59 +00002462 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002463 Result = Type.getAsString(Policy);
2464 std::string Quals =
2465 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2466 if (!Quals.empty())
2467 Result = "(" + Quals + " " + Result + ")";
2468 if (Result.back() != ')')
2469 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002470 if (Param->getIdentifier())
2471 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002472 } else {
2473 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002474 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002475
Douglas Gregore90dd002010-08-24 16:15:59 +00002476 return Result;
2477 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002478
Douglas Gregore90dd002010-08-24 16:15:59 +00002479 // We have the function prototype behind the block pointer type, as it was
2480 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002481 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2482 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002483 ObjCSubsts);
2484}
2485
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002486/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002487/// declaration.
2488///
2489/// \param BlockDecl A declaration with an Objective-C block type.
2490///
2491/// \param Block The most relevant type location for that block type.
2492///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002493/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002494/// declaration is included in the resulting string.
2495static std::string
2496formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2497 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002498 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002499 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002500 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002501 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002502 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002503 ResultType =
2504 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2505 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002506 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002507 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002508
2509 // Format the parameter list.
2510 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002511 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002512 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002513 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002514 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002515 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002516 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002517 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002518 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002519 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002520 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002521 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002522 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002523 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002524
David Blaikie6adc78e2013-02-18 22:06:02 +00002525 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002526 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002527 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002528 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002529 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002530
Douglas Gregord793e7c2011-10-18 04:23:19 +00002531 if (SuppressBlock) {
2532 // Format as a parameter.
2533 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002534 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002535 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002536 Result += ")";
2537 Result += Params;
2538 } else {
2539 // Format as a block literal argument.
2540 Result = '^' + Result;
2541 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002542
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002543 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002544 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002545 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002546
Douglas Gregore90dd002010-08-24 16:15:59 +00002547 return Result;
2548}
2549
Erik Verbruggen11338c52017-07-19 10:45:40 +00002550static std::string GetDefaultValueString(const ParmVarDecl *Param,
2551 const SourceManager &SM,
2552 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002553 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002554 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2555 bool Invalid = CharSrcRange.isInvalid();
2556 if (Invalid)
2557 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002558 StringRef srcText =
2559 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002560 if (Invalid)
2561 return "";
2562
2563 if (srcText.empty() || srcText == "=") {
2564 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002565 // This happens if the code is incorrect (for example class is forward
2566 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002567 return "";
2568 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002569 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002570 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2571 // this value always has (or always does not have) '=' in front of it
2572 if (DefValue.at(0) != '=') {
2573 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002574 // Lexer returns built-in types values without '=' and user-defined types
2575 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002576 return " = " + DefValue;
2577 }
2578 return " " + DefValue;
2579}
2580
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002581/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002582static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002583 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002584 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002585 CodeCompletionBuilder &Result,
2586 unsigned Start = 0,
2587 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002588 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002589
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002590 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002591 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002592
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002593 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002594 // When we see an optional default argument, put that argument and
2595 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002596 CodeCompletionBuilder Opt(Result.getAllocator(),
2597 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002598 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002599 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002600 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002601 Result.AddOptionalChunk(Opt.TakeString());
2602 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002603 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002604
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002605 if (FirstParameter)
2606 FirstParameter = false;
2607 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002608 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002609
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002610 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002611
Douglas Gregor3545ff42009-09-21 16:56:56 +00002612 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002613 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002614 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002615 PlaceholderStr +=
2616 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002617
Douglas Gregor400f5972010-08-31 05:13:43 +00002618 if (Function->isVariadic() && P == N - 1)
2619 PlaceholderStr += ", ...";
2620
Douglas Gregor3545ff42009-09-21 16:56:56 +00002621 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002622 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002623 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002624 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002625
Fangrui Song050229d2018-11-24 00:14:31 +00002626 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002627 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002628 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002629 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002630
Richard Smith20e883e2015-04-29 23:20:19 +00002631 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002632 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002633}
2634
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002635/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002636static void AddTemplateParameterChunks(
2637 ASTContext &Context, const PrintingPolicy &Policy,
2638 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2639 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002640 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002641
2642 // Prefer to take the template parameter names from the first declaration of
2643 // the template.
2644 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2645
Douglas Gregor3545ff42009-09-21 16:56:56 +00002646 TemplateParameterList *Params = Template->getTemplateParameters();
2647 TemplateParameterList::iterator PEnd = Params->end();
2648 if (MaxParameters)
2649 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002650 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2651 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002652 bool HasDefaultArg = false;
2653 std::string PlaceholderStr;
2654 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2655 if (TTP->wasDeclaredWithTypename())
2656 PlaceholderStr = "typename";
2657 else
2658 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002659
Douglas Gregor3545ff42009-09-21 16:56:56 +00002660 if (TTP->getIdentifier()) {
2661 PlaceholderStr += ' ';
2662 PlaceholderStr += TTP->getIdentifier()->getName();
2663 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002664
Douglas Gregor3545ff42009-09-21 16:56:56 +00002665 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002666 } else if (NonTypeTemplateParmDecl *NTTP =
2667 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002668 if (NTTP->getIdentifier())
2669 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002670 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002671 HasDefaultArg = NTTP->hasDefaultArgument();
2672 } else {
2673 assert(isa<TemplateTemplateParmDecl>(*P));
2674 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002675
Douglas Gregor3545ff42009-09-21 16:56:56 +00002676 // Since putting the template argument list into the placeholder would
2677 // be very, very long, we just use an abbreviation.
2678 PlaceholderStr = "template<...> class";
2679 if (TTP->getIdentifier()) {
2680 PlaceholderStr += ' ';
2681 PlaceholderStr += TTP->getIdentifier()->getName();
2682 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002683
Douglas Gregor3545ff42009-09-21 16:56:56 +00002684 HasDefaultArg = TTP->hasDefaultArgument();
2685 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002686
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002687 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002688 // When we see an optional default argument, put that argument and
2689 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002690 CodeCompletionBuilder Opt(Result.getAllocator(),
2691 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002692 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002693 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002694 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002695 P - Params->begin(), true);
2696 Result.AddOptionalChunk(Opt.TakeString());
2697 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002698 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002699
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002700 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002701
Douglas Gregor3545ff42009-09-21 16:56:56 +00002702 if (FirstParameter)
2703 FirstParameter = false;
2704 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002705 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002706
Douglas Gregor3545ff42009-09-21 16:56:56 +00002707 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002708 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002709 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002710 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002711}
2712
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002713/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002714/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002715static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2716 NestedNameSpecifier *Qualifier,
2717 bool QualifierIsInformative,
2718 ASTContext &Context,
2719 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002720 if (!Qualifier)
2721 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002722
Douglas Gregorf2510672009-09-21 19:57:38 +00002723 std::string PrintedNNS;
2724 {
2725 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002726 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002727 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002728 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002729 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002730 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002731 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002732}
2733
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002734static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002735AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002736 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002737 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Douglas Gregor0f622362009-12-11 18:44:16 +00002738 if (!Proto || !Proto->getTypeQuals())
2739 return;
2740
Douglas Gregor304f9b02011-02-01 21:15:40 +00002741 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002742
Douglas Gregor304f9b02011-02-01 21:15:40 +00002743 // Handle single qualifiers without copying
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00002744 if (Proto->getTypeQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002745 Result.AddInformativeChunk(" const");
2746 return;
2747 }
2748
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00002749 if (Proto->getTypeQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002750 Result.AddInformativeChunk(" volatile");
2751 return;
2752 }
2753
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00002754 if (Proto->getTypeQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002755 Result.AddInformativeChunk(" restrict");
2756 return;
2757 }
2758
2759 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002760 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002761 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002762 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002763 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002764 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002765 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002766 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002767 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002768}
2769
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002770/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002771static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002772 const NamedDecl *ND,
2773 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002774 DeclarationName Name = ND->getDeclName();
2775 if (!Name)
2776 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002777
Douglas Gregor0212fd72010-09-21 16:06:22 +00002778 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002779 case DeclarationName::CXXOperatorName: {
2780 const char *OperatorName = nullptr;
2781 switch (Name.getCXXOverloadedOperator()) {
2782 case OO_None:
2783 case OO_Conditional:
2784 case NUM_OVERLOADED_OPERATORS:
2785 OperatorName = "operator";
2786 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002787
Fangrui Song050229d2018-11-24 00:14:31 +00002788#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
2789 case OO_##Name: \
2790 OperatorName = "operator" Spelling; \
2791 break;
2792#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00002793#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002794
Fangrui Song050229d2018-11-24 00:14:31 +00002795 case OO_New:
2796 OperatorName = "operator new";
2797 break;
2798 case OO_Delete:
2799 OperatorName = "operator delete";
2800 break;
2801 case OO_Array_New:
2802 OperatorName = "operator new[]";
2803 break;
2804 case OO_Array_Delete:
2805 OperatorName = "operator delete[]";
2806 break;
2807 case OO_Call:
2808 OperatorName = "operator()";
2809 break;
2810 case OO_Subscript:
2811 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002812 break;
2813 }
Fangrui Song050229d2018-11-24 00:14:31 +00002814 Result.AddTypedTextChunk(OperatorName);
2815 break;
2816 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002817
Douglas Gregor0212fd72010-09-21 16:06:22 +00002818 case DeclarationName::Identifier:
2819 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002820 case DeclarationName::CXXDestructorName:
2821 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002822 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002823 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002824 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002825
Richard Smith35845152017-02-07 01:37:30 +00002826 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002827 case DeclarationName::CXXUsingDirective:
2828 case DeclarationName::ObjCZeroArgSelector:
2829 case DeclarationName::ObjCOneArgSelector:
2830 case DeclarationName::ObjCMultiArgSelector:
2831 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002832
Douglas Gregor0212fd72010-09-21 16:06:22 +00002833 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002834 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002835 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00002836 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00002837 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00002838 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00002839 Record = InjectedTy->getDecl();
2840 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002841 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002842 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002843 break;
2844 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002845
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002846 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002847 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002848 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002849 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002850 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002851 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002852 }
2853 break;
2854 }
2855 }
2856}
2857
Fangrui Song050229d2018-11-24 00:14:31 +00002858CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
2859 Sema &S, const CodeCompletionContext &CCContext,
2860 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
2861 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002862 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2863 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002864}
2865
Eric Liu00f43c92018-07-06 09:43:57 +00002866CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2867 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2868 CodeCompletionTUInfo &CCTUInfo) {
2869 assert(Kind == RK_Macro);
2870 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2871 const MacroInfo *MI = PP.getMacroInfo(Macro);
2872 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2873
2874 if (!MI || !MI->isFunctionLike())
2875 return Result.TakeString();
2876
2877 // Format a function-like macro with placeholders for the arguments.
2878 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2879 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2880
2881 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2882 if (MI->isC99Varargs()) {
2883 --AEnd;
2884
2885 if (A == AEnd) {
2886 Result.AddPlaceholderChunk("...");
2887 }
2888 }
2889
2890 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2891 if (A != MI->param_begin())
2892 Result.AddChunk(CodeCompletionString::CK_Comma);
2893
2894 if (MI->isVariadic() && (A + 1) == AEnd) {
2895 SmallString<32> Arg = (*A)->getName();
2896 if (MI->isC99Varargs())
2897 Arg += ", ...";
2898 else
2899 Arg += "...";
2900 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2901 break;
2902 }
2903
2904 // Non-variadic macros are simple.
2905 Result.AddPlaceholderChunk(
2906 Result.getAllocator().CopyString((*A)->getName()));
2907 }
2908 Result.AddChunk(CodeCompletionString::CK_RightParen);
2909 return Result.TakeString();
2910}
2911
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002912/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002913/// result.
2914///
2915/// \returns Either a new, heap-allocated code completion string describing
2916/// how to use this result, or NULL to indicate that the string or name of the
2917/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00002918CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
2919 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
2920 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
2921 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002922 if (Kind == RK_Macro)
2923 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2924
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002925 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002926
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002927 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002928 if (Kind == RK_Pattern) {
2929 Pattern->Priority = Priority;
2930 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002931
Douglas Gregor78254c82012-03-27 23:34:16 +00002932 if (Declaration) {
2933 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002934 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002935 if (const RawComment *RC =
2936 getPatternCompletionComment(Ctx, Declaration)) {
2937 Result.addBriefComment(RC->getBriefText(Ctx));
2938 Pattern->BriefComment = Result.getBriefComment();
2939 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002940 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002941
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002942 return Pattern;
2943 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002944
Douglas Gregorf09935f2009-12-01 05:55:20 +00002945 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002946 Result.AddTypedTextChunk(Keyword);
2947 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002948 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002949 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00002950 return createCodeCompletionStringForDecl(
2951 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002952}
2953
2954CodeCompletionString *
2955CodeCompletionResult::createCodeCompletionStringForOverride(
2956 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2957 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2958 PrintingPolicy &Policy) {
2959 std::string OverrideSignature;
2960 llvm::raw_string_ostream OS(OverrideSignature);
2961 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
2962 /*IncludeBriefComments=*/false,
2963 CCContext, Policy);
2964 printOverrideString(OS, CCS);
2965 OS << " override";
2966 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
2967 return Result.TakeString();
2968}
2969
2970CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
2971 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2972 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2973 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002974 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002975 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002976
2977 if (IncludeBriefComments) {
2978 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002979 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002980 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002981 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002982 }
2983
Douglas Gregor9eb77012009-11-07 00:00:49 +00002984 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002985 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002986 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002987 Result.AddTextChunk("::");
2988 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002989 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002990
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002991 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2992 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002993
Douglas Gregorc3425b12015-07-07 06:20:19 +00002994 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002995
Fangrui Song050229d2018-11-24 00:14:31 +00002996 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002997 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002998 Ctx, Policy);
2999 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003000 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003001 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003002 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003003 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003004 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003005 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003006
Fangrui Song050229d2018-11-24 00:14:31 +00003007 if (const FunctionTemplateDecl *FunTmpl =
3008 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003009 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003010 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003011 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003012 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003013
Douglas Gregor3545ff42009-09-21 16:56:56 +00003014 // Figure out which template parameters are deduced (or have default
3015 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003016 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003017 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003018 unsigned LastDeducibleArgument;
3019 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3020 --LastDeducibleArgument) {
3021 if (!Deduced[LastDeducibleArgument - 1]) {
3022 // C++0x: Figure out if the template argument has a default. If so,
3023 // the user doesn't need to type this argument.
3024 // FIXME: We need to abstract template parameters better!
3025 bool HasDefaultArg = false;
3026 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003027 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003028 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3029 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003030 else if (NonTypeTemplateParmDecl *NTTP =
3031 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003032 HasDefaultArg = NTTP->hasDefaultArgument();
3033 else {
3034 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003035 HasDefaultArg =
3036 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003037 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003038
Douglas Gregor3545ff42009-09-21 16:56:56 +00003039 if (!HasDefaultArg)
3040 break;
3041 }
3042 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003043
Douglas Gregor3545ff42009-09-21 16:56:56 +00003044 if (LastDeducibleArgument) {
3045 // Some of the function template arguments cannot be deduced from a
3046 // function call, so we introduce an explicit template argument list
3047 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003048 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003049 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003050 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003051 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003052 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003053
Douglas Gregor3545ff42009-09-21 16:56:56 +00003054 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003055 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003056 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003057 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003058 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003059 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003060 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003061
Fangrui Song050229d2018-11-24 00:14:31 +00003062 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003063 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003064 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003065 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003066 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003067 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003068 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003069 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003070 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003071 }
Fangrui Song050229d2018-11-24 00:14:31 +00003072 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003073 Selector Sel = Method->getSelector();
3074 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003075 Result.AddTypedTextChunk(
3076 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003077 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003078 }
3079
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003080 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003081 SelName += ':';
3082 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003083 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003084 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003085 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003086
Douglas Gregor1b605f72009-11-19 01:08:35 +00003087 // If there is only one parameter, and we're past it, add an empty
3088 // typed-text chunk since there is nothing to type.
3089 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003090 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003091 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003092 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003093 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003094 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003095 P != PEnd; (void)++P, ++Idx) {
3096 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003097 std::string Keyword;
3098 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003099 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003100 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003101 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003102 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003103 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003104 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003105 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003106 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003107 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003108
Douglas Gregor1b605f72009-11-19 01:08:35 +00003109 // If we're before the starting parameter, skip the placeholder.
3110 if (Idx < StartParameter)
3111 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003112
3113 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003114 QualType ParamType = (*P)->getType();
3115 Optional<ArrayRef<QualType>> ObjCSubsts;
3116 if (!CCContext.getBaseType().isNull())
3117 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3118
3119 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3120 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003121 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003122 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003123 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003124 ParamType = ParamType.substObjCTypeArgs(
3125 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003126 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003127 ParamType);
3128 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003129 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003130 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003131 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003132 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003133
Douglas Gregor400f5972010-08-31 05:13:43 +00003134 if (Method->isVariadic() && (P + 1) == PEnd)
3135 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003136
Douglas Gregor95887f92010-07-08 23:20:03 +00003137 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003138 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003139 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003140 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003141 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003142 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003143 }
3144
Douglas Gregor04c5f972009-12-23 00:21:46 +00003145 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003146 if (Method->param_size() == 0) {
3147 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003148 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003149 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003150 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003151 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003152 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003153 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003154
Richard Smith20e883e2015-04-29 23:20:19 +00003155 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003156 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003157
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003158 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003159 }
3160
Douglas Gregorf09935f2009-12-01 05:55:20 +00003161 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003162 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003163 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003164
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003165 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003166 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003167 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003168}
3169
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003170const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3171 const NamedDecl *ND) {
3172 if (!ND)
3173 return nullptr;
3174 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3175 return RC;
3176
3177 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003178 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003179 if (!M)
3180 return nullptr;
3181 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3182 if (!PDecl)
3183 return nullptr;
3184
3185 return Ctx.getRawCommentForAnyRedecl(PDecl);
3186}
3187
3188const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3189 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003190 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003191 if (!M || !M->isPropertyAccessor())
3192 return nullptr;
3193
3194 // Provide code completion comment for self.GetterName where
3195 // GetterName is the getter method for a property with name
3196 // different from the property name (declared via a property
3197 // getter attribute.
3198 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3199 if (!PDecl)
3200 return nullptr;
3201 if (PDecl->getGetterName() == M->getSelector() &&
3202 PDecl->getIdentifier() != M->getIdentifier()) {
3203 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3204 return RC;
3205 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3206 return RC;
3207 }
3208 return nullptr;
3209}
3210
3211const RawComment *clang::getParameterComment(
3212 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003213 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003214 auto FDecl = Result.getFunction();
3215 if (!FDecl)
3216 return nullptr;
3217 if (ArgIndex < FDecl->getNumParams())
3218 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3219 return nullptr;
3220}
3221
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003222/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003223/// string.
3224static void AddOverloadParameterChunks(ASTContext &Context,
3225 const PrintingPolicy &Policy,
3226 const FunctionDecl *Function,
3227 const FunctionProtoType *Prototype,
3228 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003229 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003230 bool InOptional = false) {
3231 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003232 unsigned NumParams =
3233 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003234
3235 for (unsigned P = Start; P != NumParams; ++P) {
3236 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3237 // When we see an optional default argument, put that argument and
3238 // the remaining default arguments into a new, optional string.
3239 CodeCompletionBuilder Opt(Result.getAllocator(),
3240 Result.getCodeCompletionTUInfo());
3241 if (!FirstParameter)
3242 Opt.AddChunk(CodeCompletionString::CK_Comma);
3243 // Optional sections are nested.
3244 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3245 CurrentArg, P, /*InOptional=*/true);
3246 Result.AddOptionalChunk(Opt.TakeString());
3247 return;
3248 }
3249
3250 if (FirstParameter)
3251 FirstParameter = false;
3252 else
3253 Result.AddChunk(CodeCompletionString::CK_Comma);
3254
3255 InOptional = false;
3256
3257 // Format the placeholder string.
3258 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003259 if (Function) {
3260 const ParmVarDecl *Param = Function->getParamDecl(P);
3261 Placeholder = FormatFunctionParameter(Policy, Param);
3262 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003263 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3264 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003265 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003266 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003267 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003268
3269 if (P == CurrentArg)
3270 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003271 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003272 else
3273 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3274 }
3275
3276 if (Prototype && Prototype->isVariadic()) {
3277 CodeCompletionBuilder Opt(Result.getAllocator(),
3278 Result.getCodeCompletionTUInfo());
3279 if (!FirstParameter)
3280 Opt.AddChunk(CodeCompletionString::CK_Comma);
3281
3282 if (CurrentArg < NumParams)
3283 Opt.AddPlaceholderChunk("...");
3284 else
3285 Opt.AddCurrentParameterChunk("...");
3286
3287 Result.AddOptionalChunk(Opt.TakeString());
3288 }
3289}
3290
Douglas Gregorf0f51982009-09-23 00:34:09 +00003291CodeCompletionString *
3292CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003293 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3294 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003295 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003296
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003297 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003298 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3299 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003300 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003301 const FunctionProtoType *Proto =
3302 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003303 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003304 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003305 // highlighted ellipsis.
3306 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003307 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003308 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003309 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3310 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3311 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003312 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003313 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003314
3315 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003316 if (IncludeBriefComments) {
3317 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003318 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003319 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003320 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003321 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003322 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003323 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003324 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003325 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003326 }
Alp Toker314cc812014-01-25 16:55:45 +00003327
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003328 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003329 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3330 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003331 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003332
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003333 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003334}
3335
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003336unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003337 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003338 bool PreferredTypeIsPointer) {
3339 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003340
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003341 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003342 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003343 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003344 Priority = CCP_Constant;
3345 if (PreferredTypeIsPointer)
3346 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003347 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003348 // Treat "YES", "NO", "true", and "false" as constants.
3349 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3350 MacroName.equals("true") || MacroName.equals("false"))
3351 Priority = CCP_Constant;
3352 // Treat "bool" as a type.
3353 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003354 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003355
Douglas Gregor6e240332010-08-16 16:18:59 +00003356 return Priority;
3357}
3358
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003359CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003360 if (!D)
3361 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003362
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003363 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003364 case Decl::Enum:
3365 return CXCursor_EnumDecl;
3366 case Decl::EnumConstant:
3367 return CXCursor_EnumConstantDecl;
3368 case Decl::Field:
3369 return CXCursor_FieldDecl;
3370 case Decl::Function:
3371 return CXCursor_FunctionDecl;
3372 case Decl::ObjCCategory:
3373 return CXCursor_ObjCCategoryDecl;
3374 case Decl::ObjCCategoryImpl:
3375 return CXCursor_ObjCCategoryImplDecl;
3376 case Decl::ObjCImplementation:
3377 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003378
Fangrui Song050229d2018-11-24 00:14:31 +00003379 case Decl::ObjCInterface:
3380 return CXCursor_ObjCInterfaceDecl;
3381 case Decl::ObjCIvar:
3382 return CXCursor_ObjCIvarDecl;
3383 case Decl::ObjCMethod:
3384 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3385 ? CXCursor_ObjCInstanceMethodDecl
3386 : CXCursor_ObjCClassMethodDecl;
3387 case Decl::CXXMethod:
3388 return CXCursor_CXXMethod;
3389 case Decl::CXXConstructor:
3390 return CXCursor_Constructor;
3391 case Decl::CXXDestructor:
3392 return CXCursor_Destructor;
3393 case Decl::CXXConversion:
3394 return CXCursor_ConversionFunction;
3395 case Decl::ObjCProperty:
3396 return CXCursor_ObjCPropertyDecl;
3397 case Decl::ObjCProtocol:
3398 return CXCursor_ObjCProtocolDecl;
3399 case Decl::ParmVar:
3400 return CXCursor_ParmDecl;
3401 case Decl::Typedef:
3402 return CXCursor_TypedefDecl;
3403 case Decl::TypeAlias:
3404 return CXCursor_TypeAliasDecl;
3405 case Decl::TypeAliasTemplate:
3406 return CXCursor_TypeAliasTemplateDecl;
3407 case Decl::Var:
3408 return CXCursor_VarDecl;
3409 case Decl::Namespace:
3410 return CXCursor_Namespace;
3411 case Decl::NamespaceAlias:
3412 return CXCursor_NamespaceAlias;
3413 case Decl::TemplateTypeParm:
3414 return CXCursor_TemplateTypeParameter;
3415 case Decl::NonTypeTemplateParm:
3416 return CXCursor_NonTypeTemplateParameter;
3417 case Decl::TemplateTemplateParm:
3418 return CXCursor_TemplateTemplateParameter;
3419 case Decl::FunctionTemplate:
3420 return CXCursor_FunctionTemplate;
3421 case Decl::ClassTemplate:
3422 return CXCursor_ClassTemplate;
3423 case Decl::AccessSpec:
3424 return CXCursor_CXXAccessSpecifier;
3425 case Decl::ClassTemplatePartialSpecialization:
3426 return CXCursor_ClassTemplatePartialSpecialization;
3427 case Decl::UsingDirective:
3428 return CXCursor_UsingDirective;
3429 case Decl::StaticAssert:
3430 return CXCursor_StaticAssert;
3431 case Decl::Friend:
3432 return CXCursor_FriendDecl;
3433 case Decl::TranslationUnit:
3434 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003435
Fangrui Song050229d2018-11-24 00:14:31 +00003436 case Decl::Using:
3437 case Decl::UnresolvedUsingValue:
3438 case Decl::UnresolvedUsingTypename:
3439 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003440
Fangrui Song050229d2018-11-24 00:14:31 +00003441 case Decl::ObjCPropertyImpl:
3442 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3443 case ObjCPropertyImplDecl::Dynamic:
3444 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003445
Fangrui Song050229d2018-11-24 00:14:31 +00003446 case ObjCPropertyImplDecl::Synthesize:
3447 return CXCursor_ObjCSynthesizeDecl;
3448 }
Bruno Riccie5bcf0b2018-12-21 17:52:13 +00003449 llvm_unreachable("Unexpected Kind!");
Fangrui Song050229d2018-11-24 00:14:31 +00003450
3451 case Decl::Import:
3452 return CXCursor_ModuleImportDecl;
3453
3454 case Decl::ObjCTypeParam:
3455 return CXCursor_TemplateTypeParameter;
3456
3457 default:
3458 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3459 switch (TD->getTagKind()) {
3460 case TTK_Interface: // fall through
3461 case TTK_Struct:
3462 return CXCursor_StructDecl;
3463 case TTK_Class:
3464 return CXCursor_ClassDecl;
3465 case TTK_Union:
3466 return CXCursor_UnionDecl;
3467 case TTK_Enum:
3468 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003469 }
Fangrui Song050229d2018-11-24 00:14:31 +00003470 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003471 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003472
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003473 return CXCursor_UnexposedDecl;
3474}
3475
Douglas Gregor55b037b2010-07-08 20:55:51 +00003476static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003477 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003478 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003479 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003480
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003481 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003482
Eric Liu88de9f62018-09-19 09:34:55 +00003483 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3484 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003485 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003486 auto MD = PP.getMacroDefinition(M->first);
3487 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003488 MacroInfo *MI = MD.getMacroInfo();
3489 if (MI && MI->isUsedForHeaderGuard())
3490 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003491
Eric Liud485df12018-09-05 14:59:17 +00003492 Results.AddResult(
3493 Result(M->first, MI,
3494 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3495 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003496 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003497 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003498
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003499 Results.ExitScope();
3500}
3501
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003502static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003503 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003504 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003505
Douglas Gregorce0e8562010-08-23 21:54:33 +00003506 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003507
Douglas Gregorce0e8562010-08-23 21:54:33 +00003508 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3509 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003510 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003511 Results.AddResult(Result("__func__", CCP_Constant));
3512 Results.ExitScope();
3513}
3514
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003515static void HandleCodeCompleteResults(Sema *S,
3516 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003517 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003518 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003519 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003520 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003521 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003522}
3523
Ilya Biryukov41109672018-12-13 15:36:32 +00003524static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003525mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003526 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003527 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003528 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003529
John McCallfaf5fb42010-08-26 23:41:50 +00003530 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003531 return CodeCompletionContext::CCC_ClassStructUnion;
3532
John McCallfaf5fb42010-08-26 23:41:50 +00003533 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003534 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003535
John McCallfaf5fb42010-08-26 23:41:50 +00003536 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003537 return CodeCompletionContext::CCC_ObjCImplementation;
3538
John McCallfaf5fb42010-08-26 23:41:50 +00003539 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003540 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003541
John McCallfaf5fb42010-08-26 23:41:50 +00003542 case Sema::PCC_Template:
3543 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003544 if (S.CurContext->isFileContext())
3545 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003546 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003547 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003548 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003549
John McCallfaf5fb42010-08-26 23:41:50 +00003550 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003551 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003552
John McCallfaf5fb42010-08-26 23:41:50 +00003553 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003554 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003555 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003556 return CodeCompletionContext::CCC_ParenthesizedExpression;
3557 else
3558 return CodeCompletionContext::CCC_Expression;
3559
3560 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003561 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003562 case Sema::PCC_Condition:
3563 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3564 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003565
John McCallfaf5fb42010-08-26 23:41:50 +00003566 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003567 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003568
John McCallfaf5fb42010-08-26 23:41:50 +00003569 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003570 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003571
3572 case Sema::PCC_ParenthesizedExpression:
3573 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003574
Douglas Gregor80039242011-02-15 20:33:25 +00003575 case Sema::PCC_LocalDeclarationSpecifiers:
3576 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003577 }
David Blaikie8a40f702012-01-17 06:56:22 +00003578
3579 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003580}
3581
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003582/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003583/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003584/// overridden function as well as adding new functionality.
3585///
3586/// \param S The semantic analysis object for which we are generating results.
3587///
3588/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003589/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003590static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3591 ResultBuilder &Results) {
3592 // Look through blocks.
3593 DeclContext *CurContext = S.CurContext;
3594 while (isa<BlockDecl>(CurContext))
3595 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003596
Douglas Gregorac322ec2010-08-27 21:18:54 +00003597 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3598 if (!Method || !Method->isVirtual())
3599 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003600
3601 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003602 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003603 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003604 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003605 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003606
Douglas Gregor75acd922011-09-27 23:30:47 +00003607 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003608 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003609 CodeCompletionBuilder Builder(Results.getAllocator(),
3610 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003611 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3612 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003613
Douglas Gregorac322ec2010-08-27 21:18:54 +00003614 // If we need a nested-name-specifier, add one now.
3615 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003616 NestedNameSpecifier *NNS = getRequiredQualification(
3617 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003618 if (NNS) {
3619 std::string Str;
3620 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003621 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003622 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003623 }
3624 } else if (!InContext->Equals(Overridden->getDeclContext()))
3625 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003626
Fangrui Song050229d2018-11-24 00:14:31 +00003627 Builder.AddTypedTextChunk(
3628 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003629 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003630 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003631 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003632 if (FirstParam)
3633 FirstParam = false;
3634 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003635 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003636
Aaron Ballman43b68be2014-03-07 17:50:17 +00003637 Builder.AddPlaceholderChunk(
3638 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003639 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003640 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003641 Results.AddResult(CodeCompletionResult(
3642 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3643 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003644 Results.Ignore(Overridden);
3645 }
3646}
3647
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003648void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003649 ModuleIdPath Path) {
3650 typedef CodeCompletionResult Result;
3651 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003652 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003653 CodeCompletionContext::CCC_Other);
3654 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003655
Douglas Gregor07f43572012-01-29 18:15:03 +00003656 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003657 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003658 typedef CodeCompletionResult Result;
3659 if (Path.empty()) {
3660 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003661 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003662 PP.getHeaderSearchInfo().collectAllModules(Modules);
3663 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3664 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003665 Builder.getAllocator().CopyString(Modules[I]->Name));
3666 Results.AddResult(Result(
3667 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3668 Modules[I]->isAvailable() ? CXAvailability_Available
3669 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003670 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003671 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003672 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003673 Module *Mod =
3674 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3675 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003676 // Enumerate submodules.
3677 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003678 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003679 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003680 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003681
Douglas Gregor07f43572012-01-29 18:15:03 +00003682 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003683 Builder.getAllocator().CopyString((*Sub)->Name));
3684 Results.AddResult(Result(
3685 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3686 (*Sub)->isAvailable() ? CXAvailability_Available
3687 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003688 }
3689 }
3690 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003691 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003692 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003693 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003694}
3695
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003696void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003697 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003698 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003699 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003700 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003701 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003702
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003703 // Determine how to filter results, e.g., so that the names of
3704 // values (functions, enumerators, function templates, etc.) are
3705 // only allowed where we can have an expression.
3706 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003707 case PCC_Namespace:
3708 case PCC_Class:
3709 case PCC_ObjCInterface:
3710 case PCC_ObjCImplementation:
3711 case PCC_ObjCInstanceVariableList:
3712 case PCC_Template:
3713 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003714 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003715 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003716 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3717 break;
3718
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003719 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003720 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003721 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003722 case PCC_ForInit:
3723 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003724 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003725 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3726 else
3727 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003728
David Blaikiebbafb8a2012-03-11 07:00:24 +00003729 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003730 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003731 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003732
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003733 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003734 // Unfiltered
3735 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003736 }
3737
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003738 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003739 // the member function to filter/prioritize the results list.
Ilya Biryukovb45d851b2018-12-19 18:01:24 +00003740 auto ThisType = getCurrentThisType();
3741 if (!ThisType.isNull())
3742 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003743
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003744 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003745 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003746 CodeCompleter->includeGlobals(),
3747 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003748
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003749 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003750 Results.ExitScope();
3751
Douglas Gregorce0e8562010-08-23 21:54:33 +00003752 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003753 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003754 case PCC_Expression:
3755 case PCC_Statement:
3756 case PCC_RecoveryInFunction:
3757 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003758 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003759 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003760
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003761 case PCC_Namespace:
3762 case PCC_Class:
3763 case PCC_ObjCInterface:
3764 case PCC_ObjCImplementation:
3765 case PCC_ObjCInstanceVariableList:
3766 case PCC_Template:
3767 case PCC_MemberTemplate:
3768 case PCC_ForInit:
3769 case PCC_Condition:
3770 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003771 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003772 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003773 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003774
Douglas Gregor9eb77012009-11-07 00:00:49 +00003775 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003776 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003777
Douglas Gregor50832e02010-09-20 22:39:41 +00003778 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003779 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003780}
3781
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003782static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003783 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003784 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00003785 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003786 ResultBuilder &Results);
3787
3788void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3789 bool AllowNonIdentifiers,
3790 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003791 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00003792 ResultBuilder Results(
3793 *this, CodeCompleter->getAllocator(),
3794 CodeCompleter->getCodeCompletionTUInfo(),
3795 AllowNestedNameSpecifiers
3796 // FIXME: Try to separate codepath leading here to deduce whether we
3797 // need an existing symbol or a new one.
3798 ? CodeCompletionContext::CCC_SymbolOrNewName
3799 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003800 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003801
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003802 // Type qualifiers can come after names.
3803 Results.AddResult(Result("const"));
3804 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003805 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003806 Results.AddResult(Result("restrict"));
3807
David Blaikiebbafb8a2012-03-11 07:00:24 +00003808 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003809 if (getLangOpts().CPlusPlus11 &&
3810 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3811 DS.getTypeSpecType() == DeclSpec::TST_struct))
3812 Results.AddResult("final");
3813
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003814 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003815 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003816 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003817
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003818 // Add nested-name-specifiers.
3819 if (AllowNestedNameSpecifiers) {
3820 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003821 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003822 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3823 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003824 CodeCompleter->includeGlobals(),
3825 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003826 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003827 }
3828 }
3829 Results.ExitScope();
3830
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003831 // If we're in a context where we might have an expression (rather than a
3832 // declaration), and what we've seen so far is an Objective-C type that could
3833 // be a receiver of a class message, this may be a class message send with
3834 // the initial opening bracket '[' missing. Add appropriate completions.
3835 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003836 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003837 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003838 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3839 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00003840 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003841 (S->getFlags() & Scope::DeclScope) != 0 &&
3842 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00003843 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
3844 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003845 ParsedType T = DS.getRepAsType();
3846 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003847 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003848 }
3849
Douglas Gregor56ccce02010-08-24 04:59:56 +00003850 // Note that we intentionally suppress macro results here, since we do not
3851 // encourage using macros to produce the names of entities.
3852
Fangrui Song050229d2018-11-24 00:14:31 +00003853 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003854 Results.data(), Results.size());
3855}
3856
Douglas Gregor68762e72010-08-23 21:17:50 +00003857struct Sema::CodeCompleteExpressionData {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003858 CodeCompleteExpressionData(QualType PreferredType = QualType())
Fangrui Song050229d2018-11-24 00:14:31 +00003859 : PreferredType(PreferredType), IntegralConstantExpression(false),
3860 ObjCCollection(false) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003861
Douglas Gregor68762e72010-08-23 21:17:50 +00003862 QualType PreferredType;
3863 bool IntegralConstantExpression;
3864 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003865 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003866};
3867
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003868/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003869/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003870void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00003871 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003872 ResultBuilder Results(
3873 *this, CodeCompleter->getAllocator(),
3874 CodeCompleter->getCodeCompletionTUInfo(),
3875 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3876 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003877 if (Data.ObjCCollection)
3878 Results.setFilter(&ResultBuilder::IsObjCCollection);
3879 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003880 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003881 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003882 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3883 else
3884 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003885
3886 if (!Data.PreferredType.isNull())
3887 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003888
Douglas Gregor68762e72010-08-23 21:17:50 +00003889 // Ignore any declarations that we were told that we don't care about.
3890 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3891 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003892
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003893 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003894 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003895 CodeCompleter->includeGlobals(),
3896 CodeCompleter->loadExternal());
3897
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003898 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003899 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003900 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003901
Douglas Gregor55b037b2010-07-08 20:55:51 +00003902 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003903 if (!Data.PreferredType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00003904 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
3905 Data.PreferredType->isMemberPointerType() ||
3906 Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003907
Fangrui Song050229d2018-11-24 00:14:31 +00003908 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00003909 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003910 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003911
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003912 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003913 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
3914 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003915 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3916 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003917}
3918
Ilya Biryukov832c4af2018-09-07 14:04:39 +00003919void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
3920 return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
3921}
3922
Douglas Gregoreda7e542010-09-18 01:28:11 +00003923void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3924 if (E.isInvalid())
3925 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003926 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003927 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003928}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003929
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003930/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003931/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00003932typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00003933
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003934/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003935static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3936 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3937 if (Interface->hasDefinition())
3938 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003939
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003940 return Interface;
3941 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003942
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003943 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3944 if (Protocol->hasDefinition())
3945 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003946
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003947 return Protocol;
3948 }
3949 return Container;
3950}
3951
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003952/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003953/// declaration \p BD.
3954static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3955 CodeCompletionBuilder &Builder,
3956 const NamedDecl *BD,
3957 const FunctionTypeLoc &BlockLoc,
3958 const FunctionProtoTypeLoc &BlockProtoLoc) {
3959 Builder.AddResultTypeChunk(
3960 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3961 Policy, Builder.getAllocator()));
3962
3963 AddTypedNameChunk(Context, Policy, BD, Builder);
3964 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3965
3966 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3967 Builder.AddPlaceholderChunk("...");
3968 } else {
3969 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3970 if (I)
3971 Builder.AddChunk(CodeCompletionString::CK_Comma);
3972
3973 // Format the placeholder string.
3974 std::string PlaceholderStr =
3975 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3976
3977 if (I == N - 1 && BlockProtoLoc &&
3978 BlockProtoLoc.getTypePtr()->isVariadic())
3979 PlaceholderStr += ", ...";
3980
3981 // Add the placeholder string.
3982 Builder.AddPlaceholderChunk(
3983 Builder.getAllocator().CopyString(PlaceholderStr));
3984 }
3985 }
3986
3987 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3988}
3989
Fangrui Song050229d2018-11-24 00:14:31 +00003990static void
3991AddObjCProperties(const CodeCompletionContext &CCContext,
3992 ObjCContainerDecl *Container, bool AllowCategories,
3993 bool AllowNullaryMethods, DeclContext *CurContext,
3994 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3995 bool IsBaseExprStatement = false,
3996 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00003997 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003998
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003999 // Retrieve the definition.
4000 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004001
Douglas Gregor9291bad2009-11-18 01:29:26 +00004002 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004003 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004004 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004005 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004006
Alex Lorenzbaef8022016-11-09 13:43:18 +00004007 // FIXME: Provide block invocation completion for non-statement
4008 // expressions.
4009 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4010 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004011 Result R = Result(P, Results.getBasePriority(P), nullptr);
4012 if (!InOriginalClass)
4013 setInBaseClass(R);
4014 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004015 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004016 }
4017
4018 // Block setter and invocation completion is provided only when we are able
4019 // to find the FunctionProtoTypeLoc with parameter names for the block.
4020 FunctionTypeLoc BlockLoc;
4021 FunctionProtoTypeLoc BlockProtoLoc;
4022 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4023 BlockProtoLoc);
4024 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004025 Result R = Result(P, Results.getBasePriority(P), nullptr);
4026 if (!InOriginalClass)
4027 setInBaseClass(R);
4028 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004029 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004030 }
4031
4032 // The default completion result for block properties should be the block
4033 // invocation completion when the base expression is a statement.
4034 CodeCompletionBuilder Builder(Results.getAllocator(),
4035 Results.getCodeCompletionTUInfo());
4036 AddObjCBlockCall(Container->getASTContext(),
4037 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4038 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004039 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4040 if (!InOriginalClass)
4041 setInBaseClass(R);
4042 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004043
4044 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004045 // statement and the block property is mutable.
4046 if (!P->isReadOnly()) {
4047 CodeCompletionBuilder Builder(Results.getAllocator(),
4048 Results.getCodeCompletionTUInfo());
4049 AddResultTypeChunk(Container->getASTContext(),
4050 getCompletionPrintingPolicy(Results.getSema()), P,
4051 CCContext.getBaseType(), Builder);
4052 Builder.AddTypedTextChunk(
4053 Results.getAllocator().CopyString(P->getName()));
4054 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004055
Alex Lorenzbaef8022016-11-09 13:43:18 +00004056 std::string PlaceholderStr = formatBlockPlaceholder(
4057 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4058 BlockProtoLoc, /*SuppressBlockName=*/true);
4059 // Add the placeholder string.
4060 Builder.AddPlaceholderChunk(
4061 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004062
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004063 // When completing blocks properties that return void the default
4064 // property completion result should show up before the setter,
4065 // otherwise the setter completion should show up before the default
4066 // property completion, as we normally want to use the result of the
4067 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004068 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004069 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004070 Results.getBasePriority(P) +
4071 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4072 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004073 : -CCD_BlockPropertySetter));
4074 if (!InOriginalClass)
4075 setInBaseClass(R);
4076 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004077 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004078 };
4079
4080 if (IsClassProperty) {
4081 for (const auto *P : Container->class_properties())
4082 AddProperty(P);
4083 } else {
4084 for (const auto *P : Container->instance_properties())
4085 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004086 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004087
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004088 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004089 if (AllowNullaryMethods) {
4090 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004091 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004092 // Adds a method result
4093 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4094 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4095 if (!Name)
4096 return;
4097 if (!AddedProperties.insert(Name).second)
4098 return;
4099 CodeCompletionBuilder Builder(Results.getAllocator(),
4100 Results.getCodeCompletionTUInfo());
4101 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4102 Builder.AddTypedTextChunk(
4103 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004104 Result R = Result(Builder.TakeString(), M,
4105 CCP_MemberDeclaration + CCD_MethodAsProperty);
4106 if (!InOriginalClass)
4107 setInBaseClass(R);
4108 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004109 };
4110
4111 if (IsClassProperty) {
4112 for (const auto *M : Container->methods()) {
4113 // Gather the class method that can be used as implicit property
4114 // getters. Methods with arguments or methods that return void aren't
4115 // added to the results as they can't be used as a getter.
4116 if (!M->getSelector().isUnarySelector() ||
4117 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4118 continue;
4119 AddMethod(M);
4120 }
4121 } else {
4122 for (auto *M : Container->methods()) {
4123 if (M->getSelector().isUnarySelector())
4124 AddMethod(M);
4125 }
Douglas Gregor95147142011-05-05 15:50:42 +00004126 }
4127 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004128
Douglas Gregor9291bad2009-11-18 01:29:26 +00004129 // Add properties in referenced protocols.
4130 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004131 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004132 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004133 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004134 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004135 /*InOriginalClass*/ false);
4136 } else if (ObjCInterfaceDecl *IFace =
4137 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004138 if (AllowCategories) {
4139 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004140 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004141 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004142 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004143 IsBaseExprStatement, IsClassProperty,
4144 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004145 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004146
Douglas Gregor9291bad2009-11-18 01:29:26 +00004147 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004148 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004149 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004150 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004151 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004152 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004153
Douglas Gregor9291bad2009-11-18 01:29:26 +00004154 // Look in the superclass.
4155 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004156 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004157 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004158 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004159 /*InOriginalClass*/ false);
4160 } else if (const auto *Category =
4161 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004162 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004163 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004164 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004165 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004166 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004167 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004168 }
4169}
4170
Fangrui Song050229d2018-11-24 00:14:31 +00004171static void
4172AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
4173 Scope *S, QualType BaseType, RecordDecl *RD,
4174 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004175 // Indicate that we are performing a member access, and the cv-qualifiers
4176 // for the base object type.
4177 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4178
4179 // Access to a C/C++ class, struct, or union.
4180 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004181 std::vector<FixItHint> FixIts;
4182 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004183 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004184 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004185 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004186 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004187 /*IncludeDependentBases=*/true,
4188 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004189
4190 if (SemaRef.getLangOpts().CPlusPlus) {
4191 if (!Results.empty()) {
4192 // The "template" keyword can follow "->" or "." in the grammar.
4193 // However, we only want to suggest the template keyword if something
4194 // is dependent.
4195 bool IsDependent = BaseType->isDependentType();
4196 if (!IsDependent) {
4197 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4198 if (DeclContext *Ctx = DepScope->getEntity()) {
4199 IsDependent = Ctx->isDependentContext();
4200 break;
4201 }
4202 }
4203
4204 if (IsDependent)
4205 Results.AddResult(CodeCompletionResult("template"));
4206 }
4207 }
4208}
4209
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004210void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004211 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004212 SourceLocation OpLoc, bool IsArrow,
4213 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004214 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004215 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004216
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004217 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4218 if (ConvertedBase.isInvalid())
4219 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004220 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4221
4222 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004223
4224 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004225 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004226 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004227 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004228
Douglas Gregor21325842011-07-07 16:03:39 +00004229 if (IsArrow) {
4230 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004231 } else {
4232 if (ConvertedBaseType->isObjCObjectPointerType() ||
4233 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004234 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004235 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004236 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4237 }
4238 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004239
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004240 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004241 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004242 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004243 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004244
Fangrui Song050229d2018-11-24 00:14:31 +00004245 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4246 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004247 if (!Base)
4248 return false;
4249
4250 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4251 if (ConvertedBase.isInvalid())
4252 return false;
4253 Base = ConvertedBase.get();
4254
4255 QualType BaseType = Base->getType();
4256
4257 if (IsArrow) {
4258 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4259 BaseType = Ptr->getPointeeType();
4260 else if (BaseType->isObjCObjectPointerType())
4261 /*Do nothing*/;
4262 else
4263 return false;
4264 }
4265
4266 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4267 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4268 Record->getDecl(),
4269 std::move(AccessOpFixIt));
4270 } else if (const auto *TST =
4271 BaseType->getAs<TemplateSpecializationType>()) {
4272 TemplateName TN = TST->getTemplateName();
4273 if (const auto *TD =
4274 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4275 CXXRecordDecl *RD = TD->getTemplatedDecl();
4276 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4277 std::move(AccessOpFixIt));
4278 }
4279 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4280 if (auto *RD = ICNT->getDecl())
4281 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4282 std::move(AccessOpFixIt));
4283 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4284 // Objective-C property reference.
4285 AddedPropertiesSet AddedProperties;
4286
4287 if (const ObjCObjectPointerType *ObjCPtr =
4288 BaseType->getAsObjCInterfacePointerType()) {
4289 // Add property results based on our interface.
4290 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4291 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4292 /*AllowNullaryMethods=*/true, CurContext,
4293 AddedProperties, Results, IsBaseExprStatement);
4294 }
4295
4296 // Add properties from the protocols in a qualified interface.
4297 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4298 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4299 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004300 IsBaseExprStatement, /*IsClassProperty*/ false,
4301 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004302 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4303 (!IsArrow && BaseType->isObjCObjectType())) {
4304 // Objective-C instance variable access.
4305 ObjCInterfaceDecl *Class = nullptr;
4306 if (const ObjCObjectPointerType *ObjCPtr =
4307 BaseType->getAs<ObjCObjectPointerType>())
4308 Class = ObjCPtr->getInterfaceDecl();
4309 else
4310 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4311
4312 // Add all ivars from this class and its superclasses.
4313 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004314 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004315 Results.setFilter(&ResultBuilder::IsObjCIvar);
4316 LookupVisibleDecls(
4317 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4318 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4319 }
4320 }
4321
4322 // FIXME: How do we cope with isa?
4323 return true;
4324 };
4325
Douglas Gregor9291bad2009-11-18 01:29:26 +00004326 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004327
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004328 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4329 if (CodeCompleter->includeFixIts()) {
4330 const CharSourceRange OpRange =
4331 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4332 CompletionSucceded |= DoCompletion(
4333 OtherOpBase, !IsArrow,
4334 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004335 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004336
Douglas Gregor9291bad2009-11-18 01:29:26 +00004337 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004338
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004339 if (!CompletionSucceded)
4340 return;
4341
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004342 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004343 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4344 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004345}
4346
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004347void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4348 IdentifierInfo &ClassName,
4349 SourceLocation ClassNameLoc,
4350 bool IsBaseExprStatement) {
4351 IdentifierInfo *ClassNamePtr = &ClassName;
4352 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4353 if (!IFace)
4354 return;
4355 CodeCompletionContext CCContext(
4356 CodeCompletionContext::CCC_ObjCPropertyAccess);
4357 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4358 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4359 &ResultBuilder::IsMember);
4360 Results.EnterNewScope();
4361 AddedPropertiesSet AddedProperties;
4362 AddObjCProperties(CCContext, IFace, true,
4363 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4364 Results, IsBaseExprStatement,
4365 /*IsClassProperty=*/true);
4366 Results.ExitScope();
4367 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4368 Results.data(), Results.size());
4369}
4370
Faisal Vali090da2d2018-01-01 18:23:28 +00004371void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004372 if (!CodeCompleter)
4373 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004374
4375 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004376 enum CodeCompletionContext::Kind ContextKind =
4377 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004378 switch ((DeclSpec::TST)TagSpec) {
4379 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004380 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004381 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004382 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004383
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004384 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004385 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004386 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004387 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004388
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004389 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004390 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004391 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004392 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004393 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004394 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004395
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004396 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004397 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004398 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004399
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004400 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4401 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004402 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004403
4404 // First pass: look for tags.
4405 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004406 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004407 CodeCompleter->includeGlobals(),
4408 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004409
Douglas Gregor39982192010-08-15 06:18:01 +00004410 if (CodeCompleter->includeGlobals()) {
4411 // Second pass: look for nested name specifiers.
4412 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004413 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4414 CodeCompleter->includeGlobals(),
4415 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004416 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004417
Douglas Gregor0ac41382010-09-23 23:01:17 +00004418 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004419 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004420}
4421
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004422static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4423 const LangOptions &LangOpts) {
4424 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4425 Results.AddResult("const");
4426 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4427 Results.AddResult("volatile");
4428 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4429 Results.AddResult("restrict");
4430 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4431 Results.AddResult("_Atomic");
4432 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4433 Results.AddResult("__unaligned");
4434}
4435
Douglas Gregor28c78432010-08-27 17:35:51 +00004436void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004437 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004438 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004439 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004440 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004441 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004442 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004443 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004444 Results.data(), Results.size());
4445}
4446
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004447void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4448 const VirtSpecifiers *VS) {
4449 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4450 CodeCompleter->getCodeCompletionTUInfo(),
4451 CodeCompletionContext::CCC_TypeQualifiers);
4452 Results.EnterNewScope();
4453 AddTypeQualifierResults(DS, Results, LangOpts);
4454 if (LangOpts.CPlusPlus11) {
4455 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004456 if (D.getContext() == DeclaratorContext::MemberContext &&
4457 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004458 if (!VS || !VS->isFinalSpecified())
4459 Results.AddResult("final");
4460 if (!VS || !VS->isOverrideSpecified())
4461 Results.AddResult("override");
4462 }
4463 }
4464 Results.ExitScope();
4465 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4466 Results.data(), Results.size());
4467}
4468
Benjamin Kramer72dae622016-02-18 15:30:24 +00004469void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4470 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4471}
4472
Douglas Gregord328d572009-09-21 18:10:23 +00004473void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004474 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004475 return;
John McCall5939b162011-08-06 07:30:58 +00004476
Richard Smithef6c43d2018-07-26 18:41:30 +00004477 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004478 // Condition expression might be invalid, do not continue in this case.
4479 if (!Switch->getCond())
4480 return;
John McCall5939b162011-08-06 07:30:58 +00004481 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4482 if (!type->isEnumeralType()) {
4483 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004484 Data.IntegralConstantExpression = true;
4485 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004486 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004487 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004488
Douglas Gregord328d572009-09-21 18:10:23 +00004489 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004490 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004491 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004492 if (EnumDecl *Def = Enum->getDefinition())
4493 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004494
Douglas Gregord328d572009-09-21 18:10:23 +00004495 // Determine which enumerators we have already seen in the switch statement.
4496 // FIXME: Ideally, we would also be able to look *past* the code-completion
4497 // token, in case we are code-completing in the middle of the switch and not
4498 // at the end. However, we aren't able to do so at the moment.
4499 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004500 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004501 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004502 SC = SC->getNextSwitchCase()) {
4503 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4504 if (!Case)
4505 continue;
4506
4507 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004508 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4509 if (auto *Enumerator =
4510 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004511 // We look into the AST of the case statement to determine which
4512 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004513 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004514 // values of each enumerator. However, value-based approach would not
4515 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004516 // template are type- and value-dependent.
4517 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004518
Douglas Gregorf2510672009-09-21 19:57:38 +00004519 // If this is a qualified-id, keep track of the nested-name-specifier
4520 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004521 //
4522 // switch (TagD.getKind()) {
4523 // case TagDecl::TK_enum:
4524 // break;
4525 // case XXX
4526 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004527 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004528 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4529 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004530 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004531 }
4532 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004533
David Blaikiebbafb8a2012-03-11 07:00:24 +00004534 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004535 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004536 // qualify the names of the enumerators that we suggest, because they
4537 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004538 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004539 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004540
Douglas Gregord328d572009-09-21 18:10:23 +00004541 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004542 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004543 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004544 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004545 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004546 for (auto *E : Enum->enumerators()) {
4547 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004548 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004549
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004550 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004551 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004552 }
4553 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004554
Douglas Gregor21325842011-07-07 16:03:39 +00004555 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004556 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004557 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004558 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4559 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004560}
4561
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004562static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004563 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004564 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004565
4566 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004567 if (!Args[I])
4568 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004569
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004570 return false;
4571}
4572
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004573typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4574
Fangrui Song050229d2018-11-24 00:14:31 +00004575static void mergeCandidatesWithResults(
4576 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
4577 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004578 if (!CandidateSet.empty()) {
4579 // Sort the overload candidate set by placing the best overloads first.
4580 std::stable_sort(
4581 CandidateSet.begin(), CandidateSet.end(),
4582 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004583 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4584 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004585 });
4586
4587 // Add the remaining viable overload candidates as code-completion results.
Fangrui Song050229d2018-11-24 00:14:31 +00004588 for (OverloadCandidate &Candidate : CandidateSet) {
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004589 if (Candidate.Function && Candidate.Function->isDeleted())
4590 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004591 if (Candidate.Viable)
4592 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004593 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004594 }
4595}
4596
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004597/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004598/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004599static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00004600 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004601
4602 // Given the overloads 'Candidates' for a function call matching all arguments
4603 // up to N, return the type of the Nth parameter if it is the same for all
4604 // overload candidates.
4605 QualType ParamType;
4606 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00004607 if (const auto *FType = Candidate.getFunctionType())
4608 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004609 if (N < Proto->getNumParams()) {
4610 if (ParamType.isNull())
4611 ParamType = Proto->getParamType(N);
4612 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00004613 ParamType.getNonReferenceType(),
4614 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004615 // Otherwise return a default-constructed QualType.
4616 return QualType();
4617 }
4618 }
4619
4620 return ParamType;
4621}
4622
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004623static QualType
4624ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4625 MutableArrayRef<ResultCandidate> Candidates,
4626 unsigned CurrentArg, SourceLocation OpenParLoc) {
4627 if (Candidates.empty())
4628 return QualType();
4629 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4630 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4631 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004632}
4633
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004634QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4635 ArrayRef<Expr *> Args,
4636 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004637 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004638 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004639
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004640 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004641 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004642 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4643 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004644 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004645 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004646
John McCall57500772009-12-16 12:17:52 +00004647 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004648 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004649 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004650
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004651 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004652
John McCall57500772009-12-16 12:17:52 +00004653 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004654 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004655 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004656 /*PartialOverloading=*/true);
4657 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4658 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4659 if (UME->hasExplicitTemplateArgs()) {
4660 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4661 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004662 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004663
4664 // Add the base as first argument (use a nullptr if the base is implicit).
4665 SmallVector<Expr *, 12> ArgExprs(
4666 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004667 ArgExprs.append(Args.begin(), Args.end());
4668 UnresolvedSet<8> Decls;
4669 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004670 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004671 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4672 /*SuppressUsedConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00004673 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004674 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004675 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004676 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004677 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00004678 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004679 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004680 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004681 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004682 !FD->getType()->getAs<FunctionProtoType>())
4683 Results.push_back(ResultCandidate(FD));
4684 else
4685 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4686 Args, CandidateSet,
4687 /*SuppressUsedConversions=*/false,
4688 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004689
4690 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4691 // If expression's type is CXXRecordDecl, it may overload the function
4692 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004693 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004694 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00004695 DeclarationName OpName =
4696 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004697 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4698 LookupQualifiedName(R, DC);
4699 R.suppressDiagnostics();
4700 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4701 ArgExprs.append(Args.begin(), Args.end());
4702 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4703 /*ExplicitArgs=*/nullptr,
4704 /*SuppressUsedConversions=*/false,
4705 /*PartialOverloading=*/true);
4706 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004707 } else {
4708 // Lastly we check whether expression's type is function pointer or
4709 // function.
4710 QualType T = NakedFn->getType();
4711 if (!T->getPointeeType().isNull())
4712 T = T->getPointeeType();
4713
4714 if (auto FP = T->getAs<FunctionProtoType>()) {
4715 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00004716 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004717 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004718 Results.push_back(ResultCandidate(FP));
4719 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004720 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004721 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004722 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004723 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004724 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004725 QualType ParamType =
4726 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4727 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004728}
4729
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004730QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4731 SourceLocation Loc,
4732 ArrayRef<Expr *> Args,
4733 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004734 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004735 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004736
4737 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004738 CXXRecordDecl *RD =
4739 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004740 if (!RD)
4741 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004742
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004743 // FIXME: Provide support for member initializers.
4744 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004745
4746 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4747
Fangrui Song050229d2018-11-24 00:14:31 +00004748 for (NamedDecl *C : LookupConstructors(RD)) {
4749 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
4750 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
4751 CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004752 /*SuppressUsedConversions=*/false,
4753 /*PartialOverloading=*/true);
Fangrui Song050229d2018-11-24 00:14:31 +00004754 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4755 AddTemplateOverloadCandidate(
4756 FTD, DeclAccessPair::make(FTD, C->getAccess()),
4757 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
4758 /*SuppressUsedConversions=*/false,
4759 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004760 }
4761 }
4762
4763 SmallVector<ResultCandidate, 8> Results;
4764 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004765 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004766}
4767
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004768QualType Sema::ProduceCtorInitMemberSignatureHelp(
4769 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4770 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4771 if (!CodeCompleter)
4772 return QualType();
4773
4774 CXXConstructorDecl *Constructor =
4775 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4776 if (!Constructor)
4777 return QualType();
4778 // FIXME: Add support for Base class constructors as well.
4779 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4780 Constructor->getParent(), SS, TemplateTypeTy, II))
4781 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4782 MemberDecl->getLocation(), ArgExprs,
4783 OpenParLoc);
4784 return QualType();
4785}
4786
John McCall48871652010-08-21 09:40:31 +00004787void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4788 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004789 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004790 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004791 return;
4792 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004793
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00004794 CodeCompleteExpressionData Data;
4795 Data.PreferredType = VD->getType();
4796 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
4797 Data.IgnoreDecls.push_back(VD);
4798
4799 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004800}
4801
4802void Sema::CodeCompleteReturn(Scope *S) {
4803 QualType ResultType;
4804 if (isa<BlockDecl>(CurContext)) {
4805 if (BlockScopeInfo *BSI = getCurBlock())
4806 ResultType = BSI->ReturnType;
Fangrui Song050229d2018-11-24 00:14:31 +00004807 } else if (const auto *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004808 ResultType = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00004809 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004810 ResultType = Method->getReturnType();
4811
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004812 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004813 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004814 else
4815 CodeCompleteExpression(S, ResultType);
4816}
4817
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004818void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004819 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004820 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004821 mapCodeCompletionContext(*this, PCC_Statement));
4822 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4823 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004824
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004825 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4826 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004827 CodeCompleter->includeGlobals(),
4828 CodeCompleter->loadExternal());
4829
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004830 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004831
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004832 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004833 CodeCompletionBuilder Builder(Results.getAllocator(),
4834 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004835 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004836 if (Results.includeCodePatterns()) {
4837 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4838 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4839 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4840 Builder.AddPlaceholderChunk("statements");
4841 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4842 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4843 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004844 Results.AddResult(Builder.TakeString());
4845
4846 // "else if" block
4847 Builder.AddTypedTextChunk("else");
4848 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4849 Builder.AddTextChunk("if");
4850 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004852 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004853 Builder.AddPlaceholderChunk("condition");
4854 else
4855 Builder.AddPlaceholderChunk("expression");
4856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004857 if (Results.includeCodePatterns()) {
4858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4859 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4860 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4861 Builder.AddPlaceholderChunk("statements");
4862 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4863 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4864 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004865 Results.AddResult(Builder.TakeString());
4866
4867 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004868
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004869 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004870 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004871
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004872 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004873 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004874
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004875 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004876 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004877}
4878
Ilya Biryukov4974d75d2018-12-13 16:06:11 +00004879static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
4880 tok::TokenKind Op) {
4881 if (!LHS)
4882 return QualType();
4883
4884 QualType LHSType = LHS->getType();
4885 if (LHSType->isPointerType()) {
4886 if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
4887 return S.getASTContext().getPointerDiffType();
4888 // Pointer difference is more common than subtracting an int from a pointer.
4889 if (Op == tok::minus)
4890 return LHSType;
4891 }
4892
4893 switch (Op) {
4894 // No way to infer the type of RHS from LHS.
4895 case tok::comma:
4896 return QualType();
4897 // Prefer the type of the left operand for all of these.
4898 // Arithmetic operations.
4899 case tok::plus:
4900 case tok::plusequal:
4901 case tok::minus:
4902 case tok::minusequal:
4903 case tok::percent:
4904 case tok::percentequal:
4905 case tok::slash:
4906 case tok::slashequal:
4907 case tok::star:
4908 case tok::starequal:
4909 // Assignment.
4910 case tok::equal:
4911 // Comparison operators.
4912 case tok::equalequal:
4913 case tok::exclaimequal:
4914 case tok::less:
4915 case tok::lessequal:
4916 case tok::greater:
4917 case tok::greaterequal:
4918 case tok::spaceship:
4919 return LHS->getType();
4920 // Binary shifts are often overloaded, so don't try to guess those.
4921 case tok::greatergreater:
4922 case tok::greatergreaterequal:
4923 case tok::lessless:
4924 case tok::lesslessequal:
4925 if (LHSType->isIntegralOrEnumerationType())
4926 return S.getASTContext().IntTy;
4927 return QualType();
4928 // Logical operators, assume we want bool.
4929 case tok::ampamp:
4930 case tok::pipepipe:
4931 case tok::caretcaret:
4932 return S.getASTContext().BoolTy;
4933 // Operators often used for bit manipulation are typically used with the type
4934 // of the left argument.
4935 case tok::pipe:
4936 case tok::pipeequal:
4937 case tok::caret:
4938 case tok::caretequal:
4939 case tok::amp:
4940 case tok::ampequal:
4941 if (LHSType->isIntegralOrEnumerationType())
4942 return LHSType;
4943 return QualType();
4944 // RHS should be a pointer to a member of the 'LHS' type, but we can't give
4945 // any particular type here.
4946 case tok::periodstar:
4947 case tok::arrowstar:
4948 return QualType();
4949 default:
Ilya Biryukov67dbeb62018-12-13 17:23:48 +00004950 // FIXME(ibiryukov): handle the missing op, re-add the assertion.
4951 // assert(false && "unhandled binary op");
Ilya Biryukov4974d75d2018-12-13 16:06:11 +00004952 return QualType();
4953 }
4954}
4955
4956void Sema::CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op) {
4957 auto PreferredType = getPreferredTypeOfBinaryRHS(*this, LHS, Op);
4958 if (!PreferredType.isNull())
4959 CodeCompleteExpression(S, PreferredType);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004960 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004961 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004962}
4963
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004964void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004965 bool EnteringContext, QualType BaseType) {
Eric Liu06d34022017-12-12 11:35:46 +00004966 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004967 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004968
Eric Liu06d34022017-12-12 11:35:46 +00004969 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4970 // "a::b::" is not corresponding to any context/namespace in the AST), since
4971 // it can be useful for global code completion which have information about
4972 // contexts/symbols that are not in the AST.
4973 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004974 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00004975 CC.setCXXScopeSpecifier(SS);
4976 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4977 return;
4978 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004979 // Always pretend to enter a context to ensure that a dependent type
4980 // resolves to a dependent record.
4981 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004982 if (!Ctx)
4983 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004984
4985 // Try to instantiate any non-dependent declaration contexts before
4986 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004987 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004988 return;
4989
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004990 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004991 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004992 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004993 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004994
Douglas Gregor3545ff42009-09-21 16:56:56 +00004995 // The "template" keyword can follow "::" in the grammar, but only
4996 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004997 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004998 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004999 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00005000
5001 // Add calls to overridden virtual functions, if there are any.
5002 //
5003 // FIXME: This isn't wonderful, because we don't know whether we're actually
5004 // in a context that permits expressions. This is a general issue with
5005 // qualified-id completions.
5006 if (!EnteringContext)
5007 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00005008 Results.ExitScope();
5009
Eric Liufead6ae2017-12-13 10:26:49 +00005010 if (CodeCompleter->includeNamespaceLevelDecls() ||
5011 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00005012 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00005013 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
5014 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00005015 /*IncludeDependentBases=*/true,
5016 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00005017 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00005018
Eric Liu06d34022017-12-12 11:35:46 +00005019 auto CC = Results.getCompletionContext();
5020 CC.setCXXScopeSpecifier(SS);
5021
5022 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
5023 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00005024}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005025
5026void Sema::CodeCompleteUsing(Scope *S) {
5027 if (!CodeCompleter)
5028 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005029
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005030 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005031 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005032 // This can be both a using alias or using
5033 // declaration, in the former we expect a new name and a
5034 // symbol in the latter case.
5035 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005036 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005037 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005038
Douglas Gregor3545ff42009-09-21 16:56:56 +00005039 // If we aren't in class scope, we could see the "namespace" keyword.
5040 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00005041 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005042
5043 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00005044 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005045 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005046 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005047 CodeCompleter->includeGlobals(),
5048 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005049 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005050
5051 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5052 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005053}
5054
5055void Sema::CodeCompleteUsingDirective(Scope *S) {
5056 if (!CodeCompleter)
5057 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005058
Douglas Gregor3545ff42009-09-21 16:56:56 +00005059 // After "using namespace", we expect to see a namespace name or namespace
5060 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005061 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005062 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005063 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005064 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005065 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005066 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005067 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005068 CodeCompleter->includeGlobals(),
5069 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00005070 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005071 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5072 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005073}
5074
Fangrui Song050229d2018-11-24 00:14:31 +00005075void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005076 if (!CodeCompleter)
5077 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005078
Ted Kremenekc37877d2013-10-08 17:08:03 +00005079 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005080 if (!S->getParent())
5081 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005082
Fangrui Song050229d2018-11-24 00:14:31 +00005083 bool SuppressedGlobalResults =
5084 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005085
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005086 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005087 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005088 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005089 ? CodeCompletionContext::CCC_Namespace
5090 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005091 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005092
Douglas Gregor0ac41382010-09-23 23:01:17 +00005093 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005094 // We only want to see those namespaces that have already been defined
5095 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005096 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005097 // definition of each namespace.
5098 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005099 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005100 NS(Ctx->decls_begin()),
5101 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005102 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005103 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005104
5105 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005106 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005107 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005108 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005109 NS = OrigToLatest.begin(),
5110 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005111 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005112 Results.AddResult(
5113 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5114 nullptr),
5115 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005116 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005117 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005118
Fangrui Song050229d2018-11-24 00:14:31 +00005119 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5120 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005121}
5122
Fangrui Song050229d2018-11-24 00:14:31 +00005123void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005124 if (!CodeCompleter)
5125 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005126
Douglas Gregor3545ff42009-09-21 16:56:56 +00005127 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005128 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005129 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005130 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005131 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005132 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005133 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005134 CodeCompleter->includeGlobals(),
5135 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005136 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5137 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005138}
5139
Douglas Gregorc811ede2009-09-18 20:05:18 +00005140void Sema::CodeCompleteOperatorName(Scope *S) {
5141 if (!CodeCompleter)
5142 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005143
John McCall276321a2010-08-25 06:19:51 +00005144 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005145 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005146 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005147 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005148 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005149 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005150
Douglas Gregor3545ff42009-09-21 16:56:56 +00005151 // Add the names of overloadable operators.
Fangrui Song050229d2018-11-24 00:14:31 +00005152#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5153 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005154 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005155#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005156
Douglas Gregor3545ff42009-09-21 16:56:56 +00005157 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005158 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005159 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005160 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005161 CodeCompleter->includeGlobals(),
5162 CodeCompleter->loadExternal());
5163
Douglas Gregor3545ff42009-09-21 16:56:56 +00005164 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005165 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005166 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005167
5168 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5169 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005170}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005171
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005172void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005173 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005174 if (!ConstructorD)
5175 return;
5176
5177 AdjustDeclIfTemplate(ConstructorD);
5178
Fangrui Song050229d2018-11-24 00:14:31 +00005179 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005180 if (!Constructor)
5181 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005182
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005183 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005184 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005185 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005186 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005187
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005188 // Fill in any already-initialized fields or base classes.
5189 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5190 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005191 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005192 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005193 InitializedBases.insert(Context.getCanonicalType(
5194 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005195 else
Fangrui Song050229d2018-11-24 00:14:31 +00005196 InitializedFields.insert(
5197 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005198 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005199
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005200 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005201 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005202 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005203 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005204
5205 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5206 CodeCompletionBuilder Builder(Results.getAllocator(),
5207 Results.getCodeCompletionTUInfo());
5208 Builder.AddTypedTextChunk(Name);
5209 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005210 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005211 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005212 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005213 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5214 Builder);
5215 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5216 return Builder.TakeString();
5217 };
5218 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5219 const NamedDecl *ND) {
5220 CodeCompletionBuilder Builder(Results.getAllocator(),
5221 Results.getCodeCompletionTUInfo());
5222 Builder.AddTypedTextChunk(Name);
5223 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5224 Builder.AddPlaceholderChunk(Type);
5225 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5226 if (ND) {
5227 auto CCR = CodeCompletionResult(
5228 Builder.TakeString(), ND,
5229 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5230 if (isa<FieldDecl>(ND))
5231 CCR.CursorKind = CXCursor_MemberRef;
5232 return Results.AddResult(CCR);
5233 }
5234 return Results.AddResult(CodeCompletionResult(
5235 Builder.TakeString(),
5236 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5237 };
5238 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5239 const char *Name, const FieldDecl *FD) {
5240 if (!RD)
5241 return AddDefaultCtorInit(Name,
5242 FD ? Results.getAllocator().CopyString(
5243 FD->getType().getAsString(Policy))
5244 : Name,
5245 FD);
5246 auto Ctors = getConstructors(Context, RD);
5247 if (Ctors.begin() == Ctors.end())
5248 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005249 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005250 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5251 CCR.CursorKind = getCursorKindForDecl(Ctor);
5252 Results.AddResult(CCR);
5253 }
5254 };
5255 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5256 const char *BaseName =
5257 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5258 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5259 AddCtorsWithName(
5260 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5261 BaseName, nullptr);
5262 };
5263 auto AddField = [&](const FieldDecl *FD) {
5264 const char *FieldName =
5265 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5266 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5267 AddCtorsWithName(
5268 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5269 FieldName, FD);
5270 };
5271
Aaron Ballman574705e2014-03-13 15:41:46 +00005272 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005273 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5274 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005275 SawLastInitializer =
5276 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5277 Context.hasSameUnqualifiedType(
5278 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005279 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005280 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005281
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005282 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005283 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005284 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005285
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005286 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005287 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005288 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5289 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005290 SawLastInitializer =
5291 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5292 Context.hasSameUnqualifiedType(
5293 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005294 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005295 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005296
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005297 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005298 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005299 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005300
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005301 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005302 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005303 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5304 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005305 SawLastInitializer = !Initializers.empty() &&
5306 Initializers.back()->isAnyMemberInitializer() &&
5307 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005308 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005309 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005310
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005311 if (!Field->getDeclName())
5312 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005313
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005314 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005315 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005316 }
5317 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005318
Douglas Gregor0ac41382010-09-23 23:01:17 +00005319 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005320 Results.data(), Results.size());
5321}
5322
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005323/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005324static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005325 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005326 if (!DC)
5327 return false;
5328
5329 return DC->isFileContext();
5330}
5331
5332void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5333 bool AfterAmpersand) {
5334 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005335 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005336 CodeCompletionContext::CCC_Other);
5337 Results.EnterNewScope();
5338
5339 // Note what has already been captured.
5340 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5341 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005342 for (const auto &C : Intro.Captures) {
5343 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005344 IncludedThis = true;
5345 continue;
5346 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005347
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005348 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005349 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005350
Douglas Gregord8c61782012-02-15 15:34:24 +00005351 // Look for other capturable variables.
5352 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005353 for (const auto *D : S->decls()) {
5354 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005355 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005356 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005357
David Blaikie82e95a32014-11-19 07:49:47 +00005358 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005359 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005360 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005361 }
5362 }
5363
5364 // Add 'this', if it would be valid.
5365 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5366 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005367
Douglas Gregord8c61782012-02-15 15:34:24 +00005368 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005369
Douglas Gregord8c61782012-02-15 15:34:24 +00005370 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5371 Results.data(), Results.size());
5372}
5373
James Dennett596e4752012-06-14 03:11:41 +00005374/// Macro that optionally prepends an "@" to the string literal passed in via
5375/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005376#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005377
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005378static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005379 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005380 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005381 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005382 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005383
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005384 CodeCompletionBuilder Builder(Results.getAllocator(),
5385 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005386 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005387 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005388 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005389 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5390 Builder.AddPlaceholderChunk("property");
5391 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005392
Douglas Gregorf1934162010-01-13 21:24:21 +00005393 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005394 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5396 Builder.AddPlaceholderChunk("property");
5397 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005398 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005399}
5400
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005401static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005402 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005403 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005404
Douglas Gregorf1934162010-01-13 21:24:21 +00005405 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005406 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005407
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005408 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005409 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005410 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005411
Douglas Gregorf1934162010-01-13 21:24:21 +00005412 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005413 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005414
Douglas Gregorf1934162010-01-13 21:24:21 +00005415 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005416 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005417 }
5418}
5419
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005420static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005421 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005422 CodeCompletionBuilder Builder(Results.getAllocator(),
5423 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005424
Douglas Gregorf1934162010-01-13 21:24:21 +00005425 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005426 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005427 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5428 Builder.AddPlaceholderChunk("name");
5429 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005430
Douglas Gregorf4c33342010-05-28 00:22:41 +00005431 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005432 // @interface name
5433 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005434 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005435 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005436 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5437 Builder.AddPlaceholderChunk("class");
5438 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005439
Douglas Gregorf4c33342010-05-28 00:22:41 +00005440 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005441 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005442 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5443 Builder.AddPlaceholderChunk("protocol");
5444 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005445
Douglas Gregorf4c33342010-05-28 00:22:41 +00005446 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005447 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005448 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5449 Builder.AddPlaceholderChunk("class");
5450 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005451 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005452
Douglas Gregorf1934162010-01-13 21:24:21 +00005453 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005454 Builder.AddTypedTextChunk(
5455 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005456 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5457 Builder.AddPlaceholderChunk("alias");
5458 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5459 Builder.AddPlaceholderChunk("class");
5460 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005461
5462 if (Results.getSema().getLangOpts().Modules) {
5463 // @import name
5464 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5465 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5466 Builder.AddPlaceholderChunk("module");
5467 Results.AddResult(Result(Builder.TakeString()));
5468 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005469}
5470
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005471void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005472 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005473 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005474 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005475 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005476 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005477 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005478 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005479 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005480 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005481 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005482 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005483 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5484 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005485}
5486
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005487static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005488 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005489 CodeCompletionBuilder Builder(Results.getAllocator(),
5490 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005491
5492 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005493 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005494 if (Results.getSema().getLangOpts().CPlusPlus ||
5495 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005496 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005497 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005498 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005499 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5500 Builder.AddPlaceholderChunk("type-name");
5501 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5502 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005503
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005504 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005505 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005506 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005507 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5508 Builder.AddPlaceholderChunk("protocol-name");
5509 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5510 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005511
5512 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005513 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005514 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005515 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5516 Builder.AddPlaceholderChunk("selector");
5517 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5518 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005519
5520 // @"string"
5521 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005522 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005523 Builder.AddPlaceholderChunk("string");
5524 Builder.AddTextChunk("\"");
5525 Results.AddResult(Result(Builder.TakeString()));
5526
Douglas Gregor951de302012-07-17 23:24:47 +00005527 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005528 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005529 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005530 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005531 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5532 Results.AddResult(Result(Builder.TakeString()));
5533
Douglas Gregor951de302012-07-17 23:24:47 +00005534 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005535 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005536 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005537 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005538 Builder.AddChunk(CodeCompletionString::CK_Colon);
5539 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5540 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005541 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5542 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005543
Douglas Gregor951de302012-07-17 23:24:47 +00005544 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005545 Builder.AddResultTypeChunk("id");
5546 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005547 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005548 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5549 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005550}
5551
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005552static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005553 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005554 CodeCompletionBuilder Builder(Results.getAllocator(),
5555 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005556
Douglas Gregorf4c33342010-05-28 00:22:41 +00005557 if (Results.includeCodePatterns()) {
5558 // @try { statements } @catch ( declaration ) { statements } @finally
5559 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005560 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005561 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5562 Builder.AddPlaceholderChunk("statements");
5563 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5564 Builder.AddTextChunk("@catch");
5565 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5566 Builder.AddPlaceholderChunk("parameter");
5567 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5568 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5569 Builder.AddPlaceholderChunk("statements");
5570 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5571 Builder.AddTextChunk("@finally");
5572 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5573 Builder.AddPlaceholderChunk("statements");
5574 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5575 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005576 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005577
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005578 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005579 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005580 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5581 Builder.AddPlaceholderChunk("expression");
5582 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005583
Douglas Gregorf4c33342010-05-28 00:22:41 +00005584 if (Results.includeCodePatterns()) {
5585 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005586 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005587 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5588 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5589 Builder.AddPlaceholderChunk("expression");
5590 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5591 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5592 Builder.AddPlaceholderChunk("statements");
5593 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5594 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005595 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005596}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005597
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005598static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005599 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005600 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005601 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5602 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5603 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005604 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005605 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005606}
5607
5608void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005609 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005610 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005611 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005612 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005613 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005614 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005615 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5616 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005617}
5618
5619void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005620 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005621 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005622 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005623 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005624 AddObjCStatementResults(Results, false);
5625 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005626 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005627 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5628 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005629}
5630
5631void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005632 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005633 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005634 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005635 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005636 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005637 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005638 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5639 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005640}
5641
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005642/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005643/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005644static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005645 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005646 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005647 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005648
Bill Wendling44426052012-12-20 19:22:21 +00005649 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005650
Douglas Gregore6078da2009-11-19 00:14:45 +00005651 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005652 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5653 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005654 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005655
Jordan Rose53cb2f32012-08-20 20:01:13 +00005656 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00005657 unsigned AssignCopyRetMask =
5658 Attributes &
5659 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
5660 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
5661 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
5662 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005663 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005664 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005665 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005666 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5667 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005668 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005669
Douglas Gregore6078da2009-11-19 00:14:45 +00005670 return false;
5671}
5672
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005673void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005674 if (!CodeCompleter)
5675 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005676
Bill Wendling44426052012-12-20 19:22:21 +00005677 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005678
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005679 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005680 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005681 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005682 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005683 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005684 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005685 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005686 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005687 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005688 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5689 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005690 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005691 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005692 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005693 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005694 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005695 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005696 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005697 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005698 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005699 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005700 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005701 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005702
5703 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005704 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005705 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005706 Results.AddResult(CodeCompletionResult("weak"));
5707
Bill Wendling44426052012-12-20 19:22:21 +00005708 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005709 CodeCompletionBuilder Setter(Results.getAllocator(),
5710 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005711 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005712 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005713 Setter.AddPlaceholderChunk("method");
5714 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005715 }
Bill Wendling44426052012-12-20 19:22:21 +00005716 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005717 CodeCompletionBuilder Getter(Results.getAllocator(),
5718 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005719 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005720 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005721 Getter.AddPlaceholderChunk("method");
5722 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005723 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005724 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5725 Results.AddResult(CodeCompletionResult("nonnull"));
5726 Results.AddResult(CodeCompletionResult("nullable"));
5727 Results.AddResult(CodeCompletionResult("null_unspecified"));
5728 Results.AddResult(CodeCompletionResult("null_resettable"));
5729 }
Steve Naroff936354c2009-10-08 21:55:05 +00005730 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005731 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5732 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005733}
Steve Naroffeae65032009-11-07 02:08:14 +00005734
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005735/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005736/// via code completion.
5737enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005738 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5739 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00005740 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005741};
5742
Fangrui Song050229d2018-11-24 00:14:31 +00005743static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005744 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005745 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005746 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005747 if (NumSelIdents > Sel.getNumArgs())
5748 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005749
Douglas Gregor67c692c2010-08-26 15:07:07 +00005750 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00005751 case MK_Any:
5752 break;
5753 case MK_ZeroArgSelector:
5754 return Sel.isUnarySelector();
5755 case MK_OneArgSelector:
5756 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005757 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005758
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005759 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5760 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005761
Douglas Gregor67c692c2010-08-26 15:07:07 +00005762 for (unsigned I = 0; I != NumSelIdents; ++I)
5763 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5764 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005765
Douglas Gregor67c692c2010-08-26 15:07:07 +00005766 return true;
5767}
5768
Douglas Gregorc8537c52009-11-19 07:41:15 +00005769static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5770 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005771 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005772 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005773 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005774 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005775}
Douglas Gregor1154e272010-09-16 16:06:31 +00005776
Fangrui Song050229d2018-11-24 00:14:31 +00005777/// A set of selectors, which is used to avoid introducing multiple
5778/// completions with the same selector into the result set.
5779typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00005780
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005781/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005782/// container to the set of results.
5783///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005784/// The container will be a class, protocol, category, or implementation of
5785/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005786/// the superclasses of classes along with their categories, protocols, and
5787/// implementations.
5788///
5789/// \param Container the container in which we'll look to find methods.
5790///
James Dennett596e4752012-06-14 03:11:41 +00005791/// \param WantInstanceMethods Whether to add instance methods (only); if
5792/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005793///
5794/// \param CurContext the context in which we're performing the lookup that
5795/// finds methods.
5796///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005797/// \param AllowSameLength Whether we allow a method to be added to the list
5798/// when it has the same number of parameters as we have selector identifiers.
5799///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005800/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005801static void AddObjCMethods(ObjCContainerDecl *Container,
5802 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005803 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005804 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005805 VisitedSelectorSet &Selectors, bool AllowSameLength,
5806 ResultBuilder &Results, bool InOriginalClass = true,
5807 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005808 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005809 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005810 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005811 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00005812 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005813 // The instance methods on the root class can be messaged via the
5814 // metaclass.
5815 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005816 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005817 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005818 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005819 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005820 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005821
David Blaikie82e95a32014-11-19 07:49:47 +00005822 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005823 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005824
5825 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005826 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005827 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005828 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00005829 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00005830 Results.MaybeAddResult(R, CurContext);
5831 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005832 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005833
Douglas Gregorf37c9492010-09-16 15:34:59 +00005834 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005835 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005836 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00005837 const ObjCList<ObjCProtocolDecl> &Protocols =
5838 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005839 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005840 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005841 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005842 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5843 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005844 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005845 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005846
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005847 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005848 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005849
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005850 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005851 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005852 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5853 Selectors, AllowSameLength, Results, false, IsRootClass);
5854
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005855 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00005856 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005857 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005858 CurContext, Selectors, AllowSameLength, Results,
5859 InOriginalClass, IsRootClass);
5860
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005861 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00005862 const ObjCList<ObjCProtocolDecl> &Protocols =
5863 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005864 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5865 E = Protocols.end();
5866 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005867 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5868 Selectors, AllowSameLength, Results, false, IsRootClass);
5869
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005870 // Add methods in category implementations.
5871 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005872 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5873 Selectors, AllowSameLength, Results, InOriginalClass,
5874 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005875 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005876
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005877 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005878 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005879 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005880 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5881 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5882 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005883
5884 // Add methods in our implementation, if any.
5885 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005886 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5887 Selectors, AllowSameLength, Results, InOriginalClass,
5888 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005889}
5890
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005891void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005892 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005893 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005894 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00005895 if (ObjCCategoryDecl *Category =
5896 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005897 Class = Category->getClassInterface();
5898
5899 if (!Class)
5900 return;
5901 }
5902
5903 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005904 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005905 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005906 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005907 Results.EnterNewScope();
5908
Douglas Gregor1154e272010-09-16 16:06:31 +00005909 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005910 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005911 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005912 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005913 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5914 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005915}
5916
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005917void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005918 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00005919 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005920 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00005921 if (ObjCCategoryDecl *Category =
5922 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005923 Class = Category->getClassInterface();
5924
5925 if (!Class)
5926 return;
5927 }
5928
5929 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005930 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005931 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005932 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005933 Results.EnterNewScope();
5934
Douglas Gregor1154e272010-09-16 16:06:31 +00005935 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00005936 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
5937 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005938
5939 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005940 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5941 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005942}
5943
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005944void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5945 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005946 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005947 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005948 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005949 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005950
Douglas Gregor99fa2642010-08-24 01:06:58 +00005951 // Add context-sensitive, Objective-C parameter-passing keywords.
5952 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005953 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005954 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5955 Results.AddResult("in");
5956 Results.AddResult("inout");
5957 AddedInOut = true;
5958 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005959 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005960 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5961 Results.AddResult("out");
5962 if (!AddedInOut)
5963 Results.AddResult("inout");
5964 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005965 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005966 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5967 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00005968 Results.AddResult("bycopy");
5969 Results.AddResult("byref");
5970 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00005971 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005972 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5973 Results.AddResult("nonnull");
5974 Results.AddResult("nullable");
5975 Results.AddResult("null_unspecified");
5976 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005977
5978 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005979 // identifier IBAction refers to a macro, provide a completion item for
5980 // an action, e.g.,
5981 // IBAction)<#selector#>:(id)sender
5982 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005983 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005984 CodeCompletionBuilder Builder(Results.getAllocator(),
5985 Results.getCodeCompletionTUInfo(),
5986 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005987 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005988 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005989 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005990 Builder.AddChunk(CodeCompletionString::CK_Colon);
5991 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005992 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005994 Builder.AddTextChunk("sender");
5995 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5996 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005997
5998 // If we're completing the return type, provide 'instancetype'.
5999 if (!IsParameter) {
6000 Results.AddResult(CodeCompletionResult("instancetype"));
6001 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006002
Douglas Gregor99fa2642010-08-24 01:06:58 +00006003 // Add various builtin type names and specifiers.
6004 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
6005 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006006
Douglas Gregor99fa2642010-08-24 01:06:58 +00006007 // Add the various type names
6008 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
6009 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6010 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006011 CodeCompleter->includeGlobals(),
6012 CodeCompleter->loadExternal());
6013
Douglas Gregor99fa2642010-08-24 01:06:58 +00006014 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006015 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00006016
Eric Liuf5ba09f2018-07-04 10:01:18 +00006017 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00006018 Results.data(), Results.size());
6019}
6020
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006021/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006022/// that it has some more-specific class type based on knowledge of
6023/// common uses of Objective-C. This routine returns that class type,
6024/// or NULL if no better result could be determined.
6025static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00006026 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006027 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00006028 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006029
6030 Selector Sel = Msg->getSelector();
6031 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00006032 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006033
6034 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
6035 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00006036 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006037
6038 ObjCMethodDecl *Method = Msg->getMethodDecl();
6039 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00006040 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006041
6042 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00006043 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00006044 switch (Msg->getReceiverKind()) {
6045 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00006046 if (const ObjCObjectType *ObjType =
6047 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006048 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00006049 break;
6050
6051 case ObjCMessageExpr::Instance: {
6052 QualType T = Msg->getInstanceReceiver()->getType();
6053 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
6054 IFace = Ptr->getInterfaceDecl();
6055 break;
6056 }
6057
6058 case ObjCMessageExpr::SuperInstance:
6059 case ObjCMessageExpr::SuperClass:
6060 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006061 }
6062
6063 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00006064 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006065
6066 ObjCInterfaceDecl *Super = IFace->getSuperClass();
6067 if (Method->isInstanceMethod())
6068 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006069 .Case("retain", IFace)
6070 .Case("strong", IFace)
6071 .Case("autorelease", IFace)
6072 .Case("copy", IFace)
6073 .Case("copyWithZone", IFace)
6074 .Case("mutableCopy", IFace)
6075 .Case("mutableCopyWithZone", IFace)
6076 .Case("awakeFromCoder", IFace)
6077 .Case("replacementObjectFromCoder", IFace)
6078 .Case("class", IFace)
6079 .Case("classForCoder", IFace)
6080 .Case("superclass", Super)
6081 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006082
6083 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006084 .Case("new", IFace)
6085 .Case("alloc", IFace)
6086 .Case("allocWithZone", IFace)
6087 .Case("class", IFace)
6088 .Case("superclass", Super)
6089 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006090}
6091
Douglas Gregor6fc04132010-08-27 15:10:57 +00006092// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006093// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006094// function.
6095///
6096/// \param S The semantic analysis object.
6097///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006098/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006099/// the "super" keyword. Otherwise, we just need to provide the arguments.
6100///
6101/// \param SelIdents The identifiers in the selector that have already been
6102/// provided as arguments for a send to "super".
6103///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006104/// \param Results The set of results to augment.
6105///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006106/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006107/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006108static ObjCMethodDecl *
6109AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6110 ArrayRef<IdentifierInfo *> SelIdents,
6111 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006112 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6113 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006114 return nullptr;
6115
Douglas Gregor6fc04132010-08-27 15:10:57 +00006116 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6117 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006118 return nullptr;
6119
Douglas Gregor6fc04132010-08-27 15:10:57 +00006120 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006121 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006122 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6123 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006124 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006125 CurMethod->isInstanceMethod());
6126
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006127 // Check in categories or class extensions.
6128 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006129 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006130 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006131 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006132 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006133 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006134 }
6135 }
6136
Douglas Gregor6fc04132010-08-27 15:10:57 +00006137 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006138 return nullptr;
6139
Douglas Gregor6fc04132010-08-27 15:10:57 +00006140 // Check whether the superclass method has the same signature.
6141 if (CurMethod->param_size() != SuperMethod->param_size() ||
6142 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006143 return nullptr;
6144
Douglas Gregor6fc04132010-08-27 15:10:57 +00006145 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006146 CurPEnd = CurMethod->param_end(),
6147 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006148 CurP != CurPEnd; ++CurP, ++SuperP) {
6149 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006150 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006151 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006152 return nullptr;
6153
Douglas Gregor6fc04132010-08-27 15:10:57 +00006154 // Make sure we have a parameter name to forward!
6155 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006156 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006157 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006158
Douglas Gregor6fc04132010-08-27 15:10:57 +00006159 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006160 CodeCompletionBuilder Builder(Results.getAllocator(),
6161 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006162
Douglas Gregor6fc04132010-08-27 15:10:57 +00006163 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006164 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006165 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006166
6167 // If we need the "super" keyword, add it (plus some spacing).
6168 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006169 Builder.AddTypedTextChunk("super");
6170 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006171 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006172
Douglas Gregor6fc04132010-08-27 15:10:57 +00006173 Selector Sel = CurMethod->getSelector();
6174 if (Sel.isUnarySelector()) {
6175 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006176 Builder.AddTextChunk(
6177 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006178 else
Fangrui Song050229d2018-11-24 00:14:31 +00006179 Builder.AddTypedTextChunk(
6180 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006181 } else {
6182 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6183 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006184 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006185 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006186
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006187 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006188 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006189 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006190 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006191 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006192 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006193 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006194 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006195 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006196 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006197 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006198 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006199 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006200 }
6201 }
6202 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006203
Douglas Gregor78254c82012-03-27 23:34:16 +00006204 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6205 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006206 return SuperMethod;
6207}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006208
Douglas Gregora817a192010-05-27 23:06:34 +00006209void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006210 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006211 ResultBuilder Results(
6212 *this, CodeCompleter->getAllocator(),
6213 CodeCompleter->getCodeCompletionTUInfo(),
6214 CodeCompletionContext::CCC_ObjCMessageReceiver,
6215 getLangOpts().CPlusPlus11
6216 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6217 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006218
Douglas Gregora817a192010-05-27 23:06:34 +00006219 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6220 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006221 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006222 CodeCompleter->includeGlobals(),
6223 CodeCompleter->loadExternal());
6224
Douglas Gregora817a192010-05-27 23:06:34 +00006225 // If we are in an Objective-C method inside a class that has a superclass,
6226 // add "super" as an option.
6227 if (ObjCMethodDecl *Method = getCurMethodDecl())
6228 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006229 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006230 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006231
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006232 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006233 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006234
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006235 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006236 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006237
Douglas Gregora817a192010-05-27 23:06:34 +00006238 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006239
Douglas Gregora817a192010-05-27 23:06:34 +00006240 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006241 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006242 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006243 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006244}
6245
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006246void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006247 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006248 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006249 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006250 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6251 // Figure out which interface we're in.
6252 CDecl = CurMethod->getClassInterface();
6253 if (!CDecl)
6254 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006255
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006256 // Find the superclass of this class.
6257 CDecl = CDecl->getSuperClass();
6258 if (!CDecl)
6259 return;
6260
6261 if (CurMethod->isInstanceMethod()) {
6262 // We are inside an instance method, which means that the message
6263 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006264 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006265 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006266 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006267 }
6268
6269 // Fall through to send to the superclass in CDecl.
6270 } else {
6271 // "super" may be the name of a type or variable. Figure out which
6272 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006273 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006274 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006275 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6276 // "super" names an interface. Use it.
6277 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006278 if (const ObjCObjectType *Iface =
6279 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006280 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006281 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6282 // "super" names an unresolved type; we can't be more specific.
6283 } else {
6284 // Assume that "super" names some kind of value and parse that way.
6285 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006286 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006287 UnqualifiedId id;
6288 id.setIdentifier(Super, SuperLoc);
Fangrui Song050229d2018-11-24 00:14:31 +00006289 ExprResult SuperExpr =
6290 ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006291 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006292 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006293 }
6294
6295 // Fall through
6296 }
6297
John McCallba7bf592010-08-24 05:47:05 +00006298 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006299 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006300 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006301 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006302 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006303 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006304}
6305
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006306/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006307/// send, determine the preferred type (if any) for that argument expression.
6308static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6309 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006310 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006311 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006312
Douglas Gregor74661272010-09-21 00:03:25 +00006313 QualType PreferredType;
6314 unsigned BestPriority = CCP_Unlikely * 2;
6315 Result *ResultsData = Results.data();
6316 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6317 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006318 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006319 isa<ObjCMethodDecl>(R.Declaration)) {
6320 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006321 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006322 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006323 QualType MyPreferredType =
6324 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006325 if (R.Priority < BestPriority || PreferredType.isNull()) {
6326 BestPriority = R.Priority;
6327 PreferredType = MyPreferredType;
6328 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6329 MyPreferredType)) {
6330 PreferredType = QualType();
6331 }
6332 }
6333 }
6334 }
6335 }
6336
6337 return PreferredType;
6338}
6339
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006340static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006341 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006342 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006343 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006344 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006345 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006346 ObjCInterfaceDecl *CDecl = nullptr;
6347
Douglas Gregor8ce33212009-11-17 17:59:40 +00006348 // If the given name refers to an interface type, retrieve the
6349 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006350 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006351 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006352 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006353 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6354 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006355 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006356
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006357 // Add all of the factory methods in this Objective-C class, its protocols,
6358 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006359 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006360
6361 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006362 // completion.
6363 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006364 if (ObjCMethodDecl *SuperMethod =
6365 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006366 Results.Ignore(SuperMethod);
6367 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006368
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006369 // If we're inside an Objective-C method definition, prefer its selector to
6370 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006371 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006372 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006373
Douglas Gregor1154e272010-09-16 16:06:31 +00006374 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006375 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006376 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6377 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006378 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006379 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006380
Douglas Gregord720daf2010-04-06 17:30:22 +00006381 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006382 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006383 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006384 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006385 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006386 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006387 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006388 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006389 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006390
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006391 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006392 }
6393 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006394
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006395 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006396 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006397 M != MEnd; ++M) {
6398 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006399 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006400 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006401 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006402
Nico Weber2e0c8f72014-12-27 03:58:08 +00006403 Result R(MethList->getMethod(),
6404 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006405 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006406 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006407 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006408 }
6409 }
6410 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006411
6412 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006413}
Douglas Gregor6285f752010-04-06 16:40:00 +00006414
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006415void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006416 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006417 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006418 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006419
Douglas Gregor63745d52011-07-21 01:05:26 +00006420 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006421
Fangrui Song050229d2018-11-24 00:14:31 +00006422 ResultBuilder Results(
6423 *this, CodeCompleter->getAllocator(),
6424 CodeCompleter->getCodeCompletionTUInfo(),
6425 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6426 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006427
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006428 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006429 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006430
6431 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006432 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006433 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006434 // code-complete the expression using the corresponding parameter type as
6435 // our preferred type, improving completion results.
6436 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006437 QualType PreferredType =
6438 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006439 if (PreferredType.isNull())
6440 CodeCompleteOrdinaryName(S, PCC_Expression);
6441 else
6442 CodeCompleteExpression(S, PreferredType);
6443 return;
6444 }
6445
Fangrui Song050229d2018-11-24 00:14:31 +00006446 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006447 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006448}
6449
Richard Trieu2bd04012011-09-09 02:00:50 +00006450void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006451 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006452 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006453 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006454 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006455
Steve Naroffeae65032009-11-07 02:08:14 +00006456 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006457
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006458 // If necessary, apply function/array conversion to the receiver.
6459 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006460 if (RecExpr) {
6461 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6462 if (Conv.isInvalid()) // conversion failed. bail.
6463 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006464 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006465 }
Fangrui Song050229d2018-11-24 00:14:31 +00006466 QualType ReceiverType = RecExpr
6467 ? RecExpr->getType()
6468 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006469 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006470 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006471
Douglas Gregordc520b02010-11-08 21:12:30 +00006472 // If we're messaging an expression with type "id" or "Class", check
6473 // whether we know something special about the receiver that allows
6474 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006475 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006476 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6477 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006478 return CodeCompleteObjCClassMessage(
6479 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6480 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006481
Fangrui Song050229d2018-11-24 00:14:31 +00006482 ReceiverType =
6483 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006484 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006485 } else if (RecExpr && getLangOpts().CPlusPlus) {
6486 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6487 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006488 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006489 ReceiverType = RecExpr->getType();
6490 }
6491 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006492
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006493 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006494 ResultBuilder Results(
6495 *this, CodeCompleter->getAllocator(),
6496 CodeCompleter->getCodeCompletionTUInfo(),
6497 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6498 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006499
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006500 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006501
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006502 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006503 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006504 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006505 if (ObjCMethodDecl *SuperMethod =
6506 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006507 Results.Ignore(SuperMethod);
6508 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006509
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006510 // If we're inside an Objective-C method definition, prefer its selector to
6511 // others.
6512 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6513 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006514
Douglas Gregor1154e272010-09-16 16:06:31 +00006515 // Keep track of the selectors we've already added.
6516 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006517
Douglas Gregora3329fa2009-11-18 00:06:18 +00006518 // Handle messages to Class. This really isn't a message to an instance
6519 // method, so we treat it the same way we would treat a message send to a
6520 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006521 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006522 ReceiverType->isObjCQualifiedClassType()) {
6523 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6524 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006525 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6526 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006527 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006528 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006529 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006530 else if (const ObjCObjectPointerType *QualID =
6531 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006532 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006533 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006534 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6535 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006536 }
6537 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006538 else if (const ObjCObjectPointerType *IFacePtr =
6539 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006540 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006541 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006542 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006543
Douglas Gregora3329fa2009-11-18 00:06:18 +00006544 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006545 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006546 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6547 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006548 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006549 // Handle messages to "id".
6550 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006551 // We're messaging "id", so provide all instance methods we know
6552 // about as code-completion results.
6553
6554 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006555 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006556 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006557 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6558 I != N; ++I) {
6559 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006560 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006561 continue;
6562
Sebastian Redl75d8a322010-08-02 23:18:59 +00006563 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006564 }
6565 }
6566
Sebastian Redl75d8a322010-08-02 23:18:59 +00006567 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6568 MEnd = MethodPool.end();
6569 M != MEnd; ++M) {
6570 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006571 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006572 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006573 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006574
Nico Weber2e0c8f72014-12-27 03:58:08 +00006575 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006576 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006577
Nico Weber2e0c8f72014-12-27 03:58:08 +00006578 Result R(MethList->getMethod(),
6579 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006580 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006581 R.AllParametersAreInformative = false;
6582 Results.MaybeAddResult(R, CurContext);
6583 }
6584 }
6585 }
Steve Naroffeae65032009-11-07 02:08:14 +00006586 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006587
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006588 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006589 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006590 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006591 // code-complete the expression using the corresponding parameter type as
6592 // our preferred type, improving completion results.
6593 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006594 QualType PreferredType =
6595 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006596 if (PreferredType.isNull())
6597 CodeCompleteOrdinaryName(S, PCC_Expression);
6598 else
6599 CodeCompleteExpression(S, PreferredType);
6600 return;
6601 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006602
Fangrui Song050229d2018-11-24 00:14:31 +00006603 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6604 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006605}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006606
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006607void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006608 DeclGroupPtrTy IterationVar) {
6609 CodeCompleteExpressionData Data;
6610 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006611
Douglas Gregor68762e72010-08-23 21:17:50 +00006612 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006613 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006614 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6615 if (*I)
6616 Data.IgnoreDecls.push_back(*I);
6617 }
6618 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006619
Douglas Gregor68762e72010-08-23 21:17:50 +00006620 CodeCompleteExpression(S, Data);
6621}
6622
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006623void Sema::CodeCompleteObjCSelector(Scope *S,
6624 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006625 // If we have an external source, load the entire class method
6626 // pool from the AST file.
6627 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00006628 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
6629 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006630 Selector Sel = ExternalSource->GetExternalSelector(I);
6631 if (Sel.isNull() || MethodPool.count(Sel))
6632 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006633
Douglas Gregor67c692c2010-08-26 15:07:07 +00006634 ReadMethodPool(Sel);
6635 }
6636 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006637
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006638 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006639 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006640 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006641 Results.EnterNewScope();
6642 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006643 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006644 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006645
Douglas Gregor67c692c2010-08-26 15:07:07 +00006646 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006647 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006648 continue;
6649
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006650 CodeCompletionBuilder Builder(Results.getAllocator(),
6651 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006652 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006653 Builder.AddTypedTextChunk(
6654 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006655 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006656 continue;
6657 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006658
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006659 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006660 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006661 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006662 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006663 Builder.AddInformativeChunk(
6664 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006665 Accumulator.clear();
6666 }
6667 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006668
Benjamin Kramer632500c2011-07-26 16:59:25 +00006669 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006670 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006671 }
Fangrui Song050229d2018-11-24 00:14:31 +00006672 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006673 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006674 }
6675 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006676
6677 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006678 Results.data(), Results.size());
6679}
6680
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006681/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006682/// (translation unit) context.
6683static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006684 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006685 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006686 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006687
Aaron Ballman629afae2014-03-07 19:56:05 +00006688 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006689 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006690 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006691 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00006692 Results.AddResult(
6693 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
6694 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006695 }
6696}
6697
Craig Topper883dd332015-12-24 23:58:11 +00006698void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00006699 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006700 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006701 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006702 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006703
Chandler Carruthede11632016-11-04 06:06:50 +00006704 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006705 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006706
Douglas Gregora3b23b02010-12-09 21:44:02 +00006707 // Tell the result set to ignore all of the protocols we have
6708 // already seen.
6709 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006710 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00006711 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006712 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006713
Douglas Gregora3b23b02010-12-09 21:44:02 +00006714 // Add all protocols.
6715 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6716 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006717
Douglas Gregora3b23b02010-12-09 21:44:02 +00006718 Results.ExitScope();
6719 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006720
6721 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6722 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006723}
6724
6725void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006726 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006727 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006728 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006729
Chandler Carruthede11632016-11-04 06:06:50 +00006730 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006731 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006732
Douglas Gregora3b23b02010-12-09 21:44:02 +00006733 // Add all protocols.
6734 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6735 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006736
Douglas Gregora3b23b02010-12-09 21:44:02 +00006737 Results.ExitScope();
6738 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006739
6740 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6741 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006742}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006743
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006744/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006745/// the given (translation unit) context.
6746static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6747 bool OnlyForwardDeclarations,
6748 bool OnlyUnimplemented,
6749 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006750 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006751
Aaron Ballman629afae2014-03-07 19:56:05 +00006752 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006753 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006754 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006755 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006756 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00006757 Results.AddResult(
6758 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
6759 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006760 }
6761}
6762
Eric Liuf5ba09f2018-07-04 10:01:18 +00006763void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006764 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006765 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006766 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006767 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006768
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006769 if (CodeCompleter->includeGlobals()) {
6770 // Add all classes.
6771 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6772 false, Results);
6773 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006774
Douglas Gregor49c22a72009-11-18 16:26:39 +00006775 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006776
Eric Liuf5ba09f2018-07-04 10:01:18 +00006777 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6778 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006779}
6780
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006781void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006782 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006783 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006784 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006785 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006786 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006787
Douglas Gregor49c22a72009-11-18 16:26:39 +00006788 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00006789 NamedDecl *CurClass =
6790 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006791 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006792 Results.Ignore(CurClass);
6793
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006794 if (CodeCompleter->includeGlobals()) {
6795 // Add all classes.
6796 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6797 false, Results);
6798 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006799
Douglas Gregor49c22a72009-11-18 16:26:39 +00006800 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006801
Eric Liuf5ba09f2018-07-04 10:01:18 +00006802 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6803 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006804}
6805
Eric Liuf5ba09f2018-07-04 10:01:18 +00006806void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006807 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006808 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006809 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006810 Results.EnterNewScope();
6811
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006812 if (CodeCompleter->includeGlobals()) {
6813 // Add all unimplemented classes.
6814 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6815 true, Results);
6816 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006817
Douglas Gregor49c22a72009-11-18 16:26:39 +00006818 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006819
Eric Liuf5ba09f2018-07-04 10:01:18 +00006820 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6821 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006822}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006823
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006824void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006825 IdentifierInfo *ClassName,
6826 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006827 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006828
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006829 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006830 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006831 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006832
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006833 // Ignore any categories we find that have already been implemented by this
6834 // interface.
6835 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00006836 NamedDecl *CurClass =
6837 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
6838 if (ObjCInterfaceDecl *Class =
6839 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006840 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006841 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006842 }
6843
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006844 // Add all of the categories we know about.
6845 Results.EnterNewScope();
6846 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006847 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006848 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006849 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00006850 Results.AddResult(
6851 Result(Category, Results.getBasePriority(Category), nullptr),
6852 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006853 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006854
6855 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6856 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006857}
6858
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006859void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006860 IdentifierInfo *ClassName,
6861 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006862 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006863
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006864 // Find the corresponding interface. If we couldn't find the interface, the
6865 // program itself is ill-formed. However, we'll try to be helpful still by
6866 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00006867 NamedDecl *CurClass =
6868 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006869 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6870 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006871 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006872
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006873 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006874 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006875 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006876
6877 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006878 // declarations in this class and any of its superclasses, except for
6879 // already-implemented categories in the class itself.
6880 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6881 Results.EnterNewScope();
6882 bool IgnoreImplemented = true;
6883 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006884 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006885 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006886 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006887 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6888 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006889 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006890
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006891 Class = Class->getSuperClass();
6892 IgnoreImplemented = false;
6893 }
6894 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006895
6896 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6897 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006898}
Douglas Gregor5d649882009-11-18 22:32:06 +00006899
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006900void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006901 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006902 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00006903 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006904
6905 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00006906 ObjCContainerDecl *Container =
6907 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
6908 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
6909 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006910 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00006911
6912 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006913 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006914 for (const auto *D : Container->decls())
6915 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006916 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006917
Douglas Gregor5d649882009-11-18 22:32:06 +00006918 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006919 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006920 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00006921 if (ObjCImplementationDecl *ClassImpl =
6922 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006923 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006924 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006925 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006926 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006927 AddObjCProperties(CCContext,
6928 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006929 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00006930 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006931 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006932
6933 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6934 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006935}
6936
Fangrui Song050229d2018-11-24 00:14:31 +00006937void Sema::CodeCompleteObjCPropertySynthesizeIvar(
6938 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006939 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006940 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006941 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006942 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006943
6944 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00006945 ObjCContainerDecl *Container =
6946 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
6947 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
6948 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006949 return;
6950
Douglas Gregor5d649882009-11-18 22:32:06 +00006951 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006952 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00006953 if (ObjCImplementationDecl *ClassImpl =
6954 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006955 Class = ClassImpl->getClassInterface();
6956 else
Fangrui Song050229d2018-11-24 00:14:31 +00006957 Class = cast<ObjCCategoryImplDecl>(Container)
6958 ->getCategoryDecl()
6959 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00006960
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006961 // Determine the type of the property we're synthesizing.
6962 QualType PropertyType = Context.getObjCIdType();
6963 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006964 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6965 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006966 PropertyType =
6967 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006968
6969 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006970 Results.setPreferredType(PropertyType);
6971 }
6972 }
6973
Douglas Gregor5d649882009-11-18 22:32:06 +00006974 // Add all of the instance variables in this class and its superclasses.
6975 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006976 bool SawSimilarlyNamedIvar = false;
6977 std::string NameWithPrefix;
6978 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006979 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006980 std::string NameWithSuffix = PropertyName->getName().str();
6981 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00006982 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006983 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00006984 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006985 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6986 CurContext, nullptr, false);
6987
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006988 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00006989 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006990 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006991 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006992 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006993 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006994
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006995 // Reduce the priority of this result by one, to give it a slight
6996 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006997 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00006998 Results.data()[Results.size() - 1].Kind ==
6999 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007000 Results.data()[Results.size() - 1].Declaration == Ivar)
7001 Results.data()[Results.size() - 1].Priority--;
7002 }
Douglas Gregor331faa02011-04-18 14:13:53 +00007003 }
Douglas Gregor5d649882009-11-18 22:32:06 +00007004 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007005
Douglas Gregor331faa02011-04-18 14:13:53 +00007006 if (!SawSimilarlyNamedIvar) {
7007 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007008 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00007009 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00007010 typedef CodeCompletionResult Result;
7011 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007012 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00007013 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00007014
Douglas Gregor75acd922011-09-27 23:30:47 +00007015 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00007016 Builder.AddResultTypeChunk(
7017 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00007018 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00007019 Results.AddResult(
7020 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00007021 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007022
Douglas Gregor5d649882009-11-18 22:32:06 +00007023 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007024
7025 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7026 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00007027}
Douglas Gregor636a61e2010-04-07 00:21:17 +00007028
Douglas Gregor416b5752010-08-25 01:08:01 +00007029// Mapping from selectors to the methods that implement that selector, along
7030// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00007031typedef llvm::DenseMap<Selector,
7032 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
7033 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007034
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007035/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00007036/// (and its superclasses, protocols, etc.) that meet the given
7037/// criteria. Insert those methods into the map of known methods,
7038/// indexed by selector so they can be easily found.
7039static void FindImplementableMethods(ASTContext &Context,
7040 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00007041 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00007042 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00007043 KnownMethodsMap &KnownMethods,
7044 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007045 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007046 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00007047 if (!IFace->hasDefinition())
7048 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007049
7050 IFace = IFace->getDefinition();
7051 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007052
Fangrui Song050229d2018-11-24 00:14:31 +00007053 const ObjCList<ObjCProtocolDecl> &Protocols =
7054 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007055 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007056 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007057 I != E; ++I)
7058 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007059 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007060
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007061 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007062 for (auto *Cat : IFace->visible_categories()) {
7063 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007064 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00007065 }
7066
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007067 // Visit the superclass.
7068 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007069 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00007070 WantInstanceMethods, ReturnType, KnownMethods,
7071 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007072 }
7073
7074 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
7075 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007076 const ObjCList<ObjCProtocolDecl> &Protocols =
7077 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007078 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007079 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007080 I != E; ++I)
7081 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007082 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007083
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007084 // If this category is the original class, jump to the interface.
7085 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007086 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007087 WantInstanceMethods, ReturnType, KnownMethods,
7088 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007089 }
7090
7091 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007092 // Make sure we have a definition; that's what we'll walk.
7093 if (!Protocol->hasDefinition())
7094 return;
7095 Protocol = Protocol->getDefinition();
7096 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007097
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007098 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007099 const ObjCList<ObjCProtocolDecl> &Protocols =
7100 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007101 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007102 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007103 I != E; ++I)
7104 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7105 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007106 }
7107
7108 // Add methods in this container. This operation occurs last because
7109 // we want the methods from this container to override any methods
7110 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007111 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007112 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007113 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007114 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007115 continue;
7116
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007117 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007118 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007119 }
7120 }
7121}
7122
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007123/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007124/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007125static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007126 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007127 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007128 CodeCompletionBuilder &Builder) {
7129 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007130 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007131 if (!Quals.empty())
7132 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007133 Builder.AddTextChunk(
7134 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007135 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7136}
7137
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007138/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007139/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007140static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007141 if (!Class)
7142 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007143
Douglas Gregor669a25a2011-02-17 00:22:45 +00007144 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7145 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007146
Douglas Gregor669a25a2011-02-17 00:22:45 +00007147 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7148}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007149
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007150/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007151/// Key-Value Observing (KVO).
7152static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7153 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007154 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007155 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007156 ResultBuilder &Results) {
7157 IdentifierInfo *PropName = Property->getIdentifier();
7158 if (!PropName || PropName->getLength() == 0)
7159 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007160
Douglas Gregor75acd922011-09-27 23:30:47 +00007161 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7162
Douglas Gregor669a25a2011-02-17 00:22:45 +00007163 // Builder that will create each code completion.
7164 typedef CodeCompletionResult Result;
7165 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007166 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007167
Douglas Gregor669a25a2011-02-17 00:22:45 +00007168 // The selector table.
7169 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007170
Douglas Gregor669a25a2011-02-17 00:22:45 +00007171 // The property name, copied into the code completion allocation region
7172 // on demand.
7173 struct KeyHolder {
7174 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007175 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007176 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007177
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007178 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007179 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007180
Douglas Gregor669a25a2011-02-17 00:22:45 +00007181 operator const char *() {
7182 if (CopiedKey)
7183 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007184
Douglas Gregor669a25a2011-02-17 00:22:45 +00007185 return CopiedKey = Allocator.CopyString(Key);
7186 }
7187 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007188
Douglas Gregor669a25a2011-02-17 00:22:45 +00007189 // The uppercased name of the property name.
7190 std::string UpperKey = PropName->getName();
7191 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007192 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007193
Fangrui Song050229d2018-11-24 00:14:31 +00007194 bool ReturnTypeMatchesProperty =
7195 ReturnType.isNull() ||
7196 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7197 Property->getType());
7198 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007199
Douglas Gregor669a25a2011-02-17 00:22:45 +00007200 // Add the normal accessor -(type)key.
7201 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007202 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007203 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7204 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007205 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7206 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007207
Douglas Gregor669a25a2011-02-17 00:22:45 +00007208 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007209 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007210 CXCursor_ObjCInstanceMethodDecl));
7211 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007212
Douglas Gregor669a25a2011-02-17 00:22:45 +00007213 // If we have an integral or boolean property (or the user has provided
7214 // an integral or boolean return type), add the accessor -(type)isKey.
7215 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007216 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007217 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007218 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7219 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007220 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007221 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007222 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7223 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007224 if (ReturnType.isNull()) {
7225 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7226 Builder.AddTextChunk("BOOL");
7227 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7228 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007229
Fangrui Song050229d2018-11-24 00:14:31 +00007230 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007231 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007232 CXCursor_ObjCInstanceMethodDecl));
7233 }
7234 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007235
Douglas Gregor669a25a2011-02-17 00:22:45 +00007236 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007237 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007238 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007239 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007240 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007241 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007242 if (ReturnType.isNull()) {
7243 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7244 Builder.AddTextChunk("void");
7245 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7246 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007247
Fangrui Song050229d2018-11-24 00:14:31 +00007248 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007249 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007250 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7251 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007252 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007253 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007254 CXCursor_ObjCInstanceMethodDecl));
7255 }
7256 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007257
Douglas Gregor669a25a2011-02-17 00:22:45 +00007258 // Indexed and unordered accessors
7259 unsigned IndexedGetterPriority = CCP_CodePattern;
7260 unsigned IndexedSetterPriority = CCP_CodePattern;
7261 unsigned UnorderedGetterPriority = CCP_CodePattern;
7262 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007263 if (const auto *ObjCPointer =
7264 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007265 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7266 // If this interface type is not provably derived from a known
7267 // collection, penalize the corresponding completions.
7268 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007269 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007270 if (!InheritsFromClassNamed(IFace, "NSArray"))
7271 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7272 }
7273
7274 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007275 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007276 if (!InheritsFromClassNamed(IFace, "NSSet"))
7277 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7278 }
7279 }
7280 } else {
7281 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7282 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7283 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7284 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7285 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007286
Douglas Gregor669a25a2011-02-17 00:22:45 +00007287 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007288 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007289 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007290 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007291 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007292 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7293 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007294 if (ReturnType.isNull()) {
7295 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7296 Builder.AddTextChunk("NSUInteger");
7297 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7298 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007299
Fangrui Song050229d2018-11-24 00:14:31 +00007300 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7301 Results.AddResult(
7302 Result(Builder.TakeString(),
7303 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7304 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007305 }
7306 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007307
Douglas Gregor669a25a2011-02-17 00:22:45 +00007308 // Indexed getters
7309 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7310 if (IsInstanceMethod &&
7311 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007312 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007313 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007314 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007315 if (ReturnType.isNull()) {
7316 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7317 Builder.AddTextChunk("id");
7318 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7319 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007320
Douglas Gregor669a25a2011-02-17 00:22:45 +00007321 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7322 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7323 Builder.AddTextChunk("NSUInteger");
7324 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7325 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007326 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007327 CXCursor_ObjCInstanceMethodDecl));
7328 }
7329 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007330
Douglas Gregor669a25a2011-02-17 00:22:45 +00007331 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7332 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007333 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007334 (ReturnType->isObjCObjectPointerType() &&
7335 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007336 ReturnType->getAs<ObjCObjectPointerType>()
7337 ->getInterfaceDecl()
7338 ->getName() == "NSArray"))) {
7339 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007340 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007341 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007342 if (ReturnType.isNull()) {
7343 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7344 Builder.AddTextChunk("NSArray *");
7345 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7346 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007347
Douglas Gregor669a25a2011-02-17 00:22:45 +00007348 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7349 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7350 Builder.AddTextChunk("NSIndexSet *");
7351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7352 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007353 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007354 CXCursor_ObjCInstanceMethodDecl));
7355 }
7356 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007357
Douglas Gregor669a25a2011-02-17 00:22:45 +00007358 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7359 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007360 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007361 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7362 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007363
David Blaikie82e95a32014-11-19 07:49:47 +00007364 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007365 if (ReturnType.isNull()) {
7366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7367 Builder.AddTextChunk("void");
7368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7369 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007370
Douglas Gregor669a25a2011-02-17 00:22:45 +00007371 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7372 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7373 Builder.AddPlaceholderChunk("object-type");
7374 Builder.AddTextChunk(" **");
7375 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7376 Builder.AddTextChunk("buffer");
7377 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7378 Builder.AddTypedTextChunk("range:");
7379 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7380 Builder.AddTextChunk("NSRange");
7381 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7382 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007383 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007384 CXCursor_ObjCInstanceMethodDecl));
7385 }
7386 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007387
Douglas Gregor669a25a2011-02-17 00:22:45 +00007388 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007389
Douglas Gregor669a25a2011-02-17 00:22:45 +00007390 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7391 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007392 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007393 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7394 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007395
David Blaikie82e95a32014-11-19 07:49:47 +00007396 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007397 if (ReturnType.isNull()) {
7398 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7399 Builder.AddTextChunk("void");
7400 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7401 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007402
Douglas Gregor669a25a2011-02-17 00:22:45 +00007403 Builder.AddTypedTextChunk("insertObject:");
7404 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7405 Builder.AddPlaceholderChunk("object-type");
7406 Builder.AddTextChunk(" *");
7407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7408 Builder.AddTextChunk("object");
7409 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7410 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7411 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7412 Builder.AddPlaceholderChunk("NSUInteger");
7413 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7414 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007415 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007416 CXCursor_ObjCInstanceMethodDecl));
7417 }
7418 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007419
Douglas Gregor669a25a2011-02-17 00:22:45 +00007420 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7421 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007422 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007423 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7424 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007425
David Blaikie82e95a32014-11-19 07:49:47 +00007426 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007427 if (ReturnType.isNull()) {
7428 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7429 Builder.AddTextChunk("void");
7430 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7431 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007432
Douglas Gregor669a25a2011-02-17 00:22:45 +00007433 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7434 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7435 Builder.AddTextChunk("NSArray *");
7436 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7437 Builder.AddTextChunk("array");
7438 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7439 Builder.AddTypedTextChunk("atIndexes:");
7440 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7441 Builder.AddPlaceholderChunk("NSIndexSet *");
7442 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7443 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007444 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007445 CXCursor_ObjCInstanceMethodDecl));
7446 }
7447 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007448
Douglas Gregor669a25a2011-02-17 00:22:45 +00007449 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7450 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007451 std::string SelectorName =
7452 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007453 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007454 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007455 if (ReturnType.isNull()) {
7456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7457 Builder.AddTextChunk("void");
7458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7459 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007460
Douglas Gregor669a25a2011-02-17 00:22:45 +00007461 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7462 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7463 Builder.AddTextChunk("NSUInteger");
7464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7465 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007466 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007467 CXCursor_ObjCInstanceMethodDecl));
7468 }
7469 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007470
Douglas Gregor669a25a2011-02-17 00:22:45 +00007471 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7472 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007473 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007474 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007475 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007476 if (ReturnType.isNull()) {
7477 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7478 Builder.AddTextChunk("void");
7479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7480 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007481
Douglas Gregor669a25a2011-02-17 00:22:45 +00007482 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7483 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7484 Builder.AddTextChunk("NSIndexSet *");
7485 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7486 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007487 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007488 CXCursor_ObjCInstanceMethodDecl));
7489 }
7490 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007491
Douglas Gregor669a25a2011-02-17 00:22:45 +00007492 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7493 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007494 std::string SelectorName =
7495 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7496 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7497 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007498
David Blaikie82e95a32014-11-19 07:49:47 +00007499 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007500 if (ReturnType.isNull()) {
7501 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7502 Builder.AddTextChunk("void");
7503 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7504 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007505
Douglas Gregor669a25a2011-02-17 00:22:45 +00007506 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7507 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7508 Builder.AddPlaceholderChunk("NSUInteger");
7509 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7510 Builder.AddTextChunk("index");
7511 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7512 Builder.AddTypedTextChunk("withObject:");
7513 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7514 Builder.AddTextChunk("id");
7515 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7516 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007517 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007518 CXCursor_ObjCInstanceMethodDecl));
7519 }
7520 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007521
Douglas Gregor669a25a2011-02-17 00:22:45 +00007522 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7523 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007524 std::string SelectorName1 =
7525 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007526 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007527 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7528 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007529
David Blaikie82e95a32014-11-19 07:49:47 +00007530 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007531 if (ReturnType.isNull()) {
7532 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7533 Builder.AddTextChunk("void");
7534 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7535 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007536
Douglas Gregor669a25a2011-02-17 00:22:45 +00007537 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7538 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7539 Builder.AddPlaceholderChunk("NSIndexSet *");
7540 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7541 Builder.AddTextChunk("indexes");
7542 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7543 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7544 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7545 Builder.AddTextChunk("NSArray *");
7546 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7547 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007548 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007549 CXCursor_ObjCInstanceMethodDecl));
7550 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007551 }
7552
Douglas Gregor669a25a2011-02-17 00:22:45 +00007553 // Unordered getters
7554 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007555 if (IsInstanceMethod &&
7556 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007557 (ReturnType->isObjCObjectPointerType() &&
7558 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007559 ReturnType->getAs<ObjCObjectPointerType>()
7560 ->getInterfaceDecl()
7561 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007562 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007563 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007564 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7565 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007566 if (ReturnType.isNull()) {
7567 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7568 Builder.AddTextChunk("NSEnumerator *");
7569 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7570 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007571
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007573 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007574 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007575 }
7576 }
7577
7578 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007579 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007580 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007581 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007582 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007583 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007584 if (ReturnType.isNull()) {
7585 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7586 Builder.AddPlaceholderChunk("object-type");
7587 Builder.AddTextChunk(" *");
7588 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7589 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007590
Douglas Gregor669a25a2011-02-17 00:22:45 +00007591 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7592 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7593 if (ReturnType.isNull()) {
7594 Builder.AddPlaceholderChunk("object-type");
7595 Builder.AddTextChunk(" *");
7596 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007597 Builder.AddTextChunk(GetCompletionTypeString(
7598 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007599 }
7600 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7601 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007602 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007603 CXCursor_ObjCInstanceMethodDecl));
7604 }
7605 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007606
Douglas Gregor669a25a2011-02-17 00:22:45 +00007607 // Mutable unordered accessors
7608 // - (void)addKeyObject:(type *)object
7609 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007610 std::string SelectorName =
7611 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007612 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007613 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007614 if (ReturnType.isNull()) {
7615 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7616 Builder.AddTextChunk("void");
7617 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7618 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007619
Douglas Gregor669a25a2011-02-17 00:22:45 +00007620 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7621 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7622 Builder.AddPlaceholderChunk("object-type");
7623 Builder.AddTextChunk(" *");
7624 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7625 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007626 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007627 CXCursor_ObjCInstanceMethodDecl));
7628 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007629 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007630
7631 // - (void)addKey:(NSSet *)objects
7632 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007633 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007634 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007635 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007636 if (ReturnType.isNull()) {
7637 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7638 Builder.AddTextChunk("void");
7639 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7640 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007641
Douglas Gregor669a25a2011-02-17 00:22:45 +00007642 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7643 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7644 Builder.AddTextChunk("NSSet *");
7645 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7646 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007647 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007648 CXCursor_ObjCInstanceMethodDecl));
7649 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007650 }
7651
Douglas Gregor669a25a2011-02-17 00:22:45 +00007652 // - (void)removeKeyObject:(type *)object
7653 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007654 std::string SelectorName =
7655 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007656 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007657 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007658 if (ReturnType.isNull()) {
7659 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7660 Builder.AddTextChunk("void");
7661 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7662 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007663
Douglas Gregor669a25a2011-02-17 00:22:45 +00007664 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7665 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7666 Builder.AddPlaceholderChunk("object-type");
7667 Builder.AddTextChunk(" *");
7668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7669 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007670 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007671 CXCursor_ObjCInstanceMethodDecl));
7672 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007673 }
7674
Douglas Gregor669a25a2011-02-17 00:22:45 +00007675 // - (void)removeKey:(NSSet *)objects
7676 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007677 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007678 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007679 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007680 if (ReturnType.isNull()) {
7681 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7682 Builder.AddTextChunk("void");
7683 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7684 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007685
Douglas Gregor669a25a2011-02-17 00:22:45 +00007686 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7687 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7688 Builder.AddTextChunk("NSSet *");
7689 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7690 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007691 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007692 CXCursor_ObjCInstanceMethodDecl));
7693 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007694 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007695
7696 // - (void)intersectKey:(NSSet *)objects
7697 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007698 std::string SelectorName = (Twine("intersect") + UpperKey).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("void");
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("NSSet *");
7710 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7711 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007712 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007713 CXCursor_ObjCInstanceMethodDecl));
7714 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007715 }
7716
Douglas Gregor669a25a2011-02-17 00:22:45 +00007717 // Key-Value Observing
7718 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007719 if (!IsInstanceMethod &&
7720 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007721 (ReturnType->isObjCObjectPointerType() &&
7722 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007723 ReturnType->getAs<ObjCObjectPointerType>()
7724 ->getInterfaceDecl()
7725 ->getName() == "NSSet"))) {
7726 std::string SelectorName =
7727 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007728 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007729 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7730 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007731 if (ReturnType.isNull()) {
7732 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007733 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007734 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7735 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007736
Douglas Gregor669a25a2011-02-17 00:22:45 +00007737 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007738 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007739 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00007740 }
7741 }
7742
7743 // + (BOOL)automaticallyNotifiesObserversForKey
7744 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00007745 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007746 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007747 std::string SelectorName =
7748 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007749 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007750 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7751 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007752 if (ReturnType.isNull()) {
7753 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7754 Builder.AddTextChunk("BOOL");
7755 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7756 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007757
Douglas Gregor857bcda2011-06-02 04:02:27 +00007758 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007759 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007760 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007761 }
7762 }
7763}
7764
Alex Lorenzb8740422017-10-24 16:39:37 +00007765void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007766 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007767 // Determine the return type of the method we're declaring, if
7768 // provided.
7769 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007770 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007771 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007772 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7773 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007774 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007775 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007776 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007777 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007778 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007779 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7780 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007781 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00007782 } else if (ObjCCategoryImplDecl *CatImpl =
7783 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007784 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007785 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007786 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007787 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007788 }
7789
7790 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007791 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007792 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007793 }
7794
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007795 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007796 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00007797 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007798 return;
7799 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007800
Douglas Gregor636a61e2010-04-07 00:21:17 +00007801 // Find all of the methods that we could declare/implement here.
7802 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00007803 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
7804 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007805
Douglas Gregor636a61e2010-04-07 00:21:17 +00007806 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007807 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007808 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007809 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007810 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007811 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007812 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007813 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007814 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007815 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007816 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007817 CodeCompletionBuilder Builder(Results.getAllocator(),
7818 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007819
7820 // Add the '-'/'+' prefix if it wasn't provided yet.
7821 if (!IsInstanceMethod) {
7822 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7823 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7824 }
7825
Douglas Gregor636a61e2010-04-07 00:21:17 +00007826 // If the result type was not already provided, add it to the
7827 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007828 if (ReturnType.isNull()) {
7829 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7830 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00007831 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
7832 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007833 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007834
7835 Selector Sel = Method->getSelector();
7836
7837 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00007838 Builder.AddTypedTextChunk(
7839 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007840
7841 // Add parameters to the pattern.
7842 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007843 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007844 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007845 P != PEnd; (void)++P, ++I) {
7846 // Add the part of the selector name.
7847 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007848 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007849 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007850 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7851 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00007852 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007853 } else
7854 break;
7855
7856 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007857 QualType ParamType;
7858 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7859 ParamType = (*P)->getType();
7860 else
7861 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00007862 ParamType = ParamType.substObjCTypeArgs(
7863 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007864 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00007865 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
7866 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007867
Douglas Gregor636a61e2010-04-07 00:21:17 +00007868 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00007869 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007870 }
7871
7872 if (Method->isVariadic()) {
7873 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007874 Builder.AddChunk(CodeCompletionString::CK_Comma);
7875 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007876 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007877
Douglas Gregord37c59d2010-05-28 00:57:46 +00007878 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007879 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007880 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7881 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7882 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007883 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007884 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007885 Builder.AddTextChunk("return");
7886 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7887 Builder.AddPlaceholderChunk("expression");
7888 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007889 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007890 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007891
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007892 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7893 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007894 }
7895
Douglas Gregor416b5752010-08-25 01:08:01 +00007896 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00007897 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007898 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00007899 setInBaseClass(R);
7900 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007901 }
7902
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007903 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00007904 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00007905 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007906 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007907 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007908
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007909 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007910 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007911 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007912 M != MEnd; ++M)
7913 KnownSelectors.insert(M->first);
7914
Douglas Gregor669a25a2011-02-17 00:22:45 +00007915 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7916 if (!IFace)
7917 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7918 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007919
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007920 if (IFace)
7921 for (auto *Cat : IFace->visible_categories())
7922 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007923
7924 if (IsInstanceMethod) {
7925 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7926 for (auto *P : Containers[I]->instance_properties())
7927 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7928 KnownSelectors, Results);
7929 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007930 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007931
Douglas Gregor636a61e2010-04-07 00:21:17 +00007932 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007933
7934 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7935 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007936}
Douglas Gregor95887f92010-07-08 23:20:03 +00007937
Fangrui Song050229d2018-11-24 00:14:31 +00007938void Sema::CodeCompleteObjCMethodDeclSelector(
7939 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
7940 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007941 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007942 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007943 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00007944 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
7945 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007946 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007947 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007948 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007949
7950 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007951 }
7952 }
7953
7954 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007955 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007956 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007957 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007958 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007959
Douglas Gregor95887f92010-07-08 23:20:03 +00007960 if (ReturnTy)
7961 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007962
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007963 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007964 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7965 MEnd = MethodPool.end();
7966 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00007967 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
7968 : &M->second.second;
7969 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007970 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007971 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007972
Douglas Gregor45879692010-07-08 23:37:41 +00007973 if (AtParameterName) {
7974 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007975 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007976 if (NumSelIdents &&
7977 NumSelIdents <= MethList->getMethod()->param_size()) {
7978 ParmVarDecl *Param =
7979 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007980 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007981 CodeCompletionBuilder Builder(Results.getAllocator(),
7982 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007983 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00007984 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007985 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007986 }
7987 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007988
Douglas Gregor45879692010-07-08 23:37:41 +00007989 continue;
7990 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007991
Nico Weber2e0c8f72014-12-27 03:58:08 +00007992 Result R(MethList->getMethod(),
7993 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007994 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007995 R.AllParametersAreInformative = false;
7996 R.DeclaringEntity = true;
7997 Results.MaybeAddResult(R, CurContext);
7998 }
7999 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008000
Douglas Gregor95887f92010-07-08 23:20:03 +00008001 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00008002
8003 if (!AtParameterName && !SelIdents.empty() &&
8004 SelIdents.front()->getName().startswith("init")) {
8005 for (const auto &M : PP.macros()) {
8006 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
8007 continue;
8008 Results.EnterNewScope();
8009 CodeCompletionBuilder Builder(Results.getAllocator(),
8010 Results.getCodeCompletionTUInfo());
8011 Builder.AddTypedTextChunk(
8012 Builder.getAllocator().CopyString(M.first->getName()));
8013 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
8014 CXCursor_MacroDefinition));
8015 Results.ExitScope();
8016 }
8017 }
8018
Eric Liuf5ba09f2018-07-04 10:01:18 +00008019 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8020 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00008021}
Douglas Gregorb14904c2010-08-13 22:48:40 +00008022
Douglas Gregorec00a262010-08-24 22:20:20 +00008023void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008024 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008025 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008026 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008027 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008028
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008029 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008030 CodeCompletionBuilder Builder(Results.getAllocator(),
8031 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008032 Builder.AddTypedTextChunk("if");
8033 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8034 Builder.AddPlaceholderChunk("condition");
8035 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008036
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008037 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008038 Builder.AddTypedTextChunk("ifdef");
8039 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8040 Builder.AddPlaceholderChunk("macro");
8041 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008042
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008043 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008044 Builder.AddTypedTextChunk("ifndef");
8045 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8046 Builder.AddPlaceholderChunk("macro");
8047 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008048
8049 if (InConditional) {
8050 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008051 Builder.AddTypedTextChunk("elif");
8052 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8053 Builder.AddPlaceholderChunk("condition");
8054 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008055
8056 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008057 Builder.AddTypedTextChunk("else");
8058 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008059
8060 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008061 Builder.AddTypedTextChunk("endif");
8062 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008063 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008064
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008065 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008066 Builder.AddTypedTextChunk("include");
8067 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8068 Builder.AddTextChunk("\"");
8069 Builder.AddPlaceholderChunk("header");
8070 Builder.AddTextChunk("\"");
8071 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008072
8073 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008074 Builder.AddTypedTextChunk("include");
8075 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8076 Builder.AddTextChunk("<");
8077 Builder.AddPlaceholderChunk("header");
8078 Builder.AddTextChunk(">");
8079 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008080
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008081 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008082 Builder.AddTypedTextChunk("define");
8083 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8084 Builder.AddPlaceholderChunk("macro");
8085 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008086
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008087 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008088 Builder.AddTypedTextChunk("define");
8089 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8090 Builder.AddPlaceholderChunk("macro");
8091 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8092 Builder.AddPlaceholderChunk("args");
8093 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8094 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008095
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008096 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008097 Builder.AddTypedTextChunk("undef");
8098 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8099 Builder.AddPlaceholderChunk("macro");
8100 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008101
8102 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008103 Builder.AddTypedTextChunk("line");
8104 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8105 Builder.AddPlaceholderChunk("number");
8106 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008107
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008108 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008109 Builder.AddTypedTextChunk("line");
8110 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8111 Builder.AddPlaceholderChunk("number");
8112 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8113 Builder.AddTextChunk("\"");
8114 Builder.AddPlaceholderChunk("filename");
8115 Builder.AddTextChunk("\"");
8116 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008117
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008118 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008119 Builder.AddTypedTextChunk("error");
8120 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8121 Builder.AddPlaceholderChunk("message");
8122 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008123
8124 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008125 Builder.AddTypedTextChunk("pragma");
8126 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8127 Builder.AddPlaceholderChunk("arguments");
8128 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008129
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008130 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008131 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008132 Builder.AddTypedTextChunk("import");
8133 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8134 Builder.AddTextChunk("\"");
8135 Builder.AddPlaceholderChunk("header");
8136 Builder.AddTextChunk("\"");
8137 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008138
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008139 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008140 Builder.AddTypedTextChunk("import");
8141 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8142 Builder.AddTextChunk("<");
8143 Builder.AddPlaceholderChunk("header");
8144 Builder.AddTextChunk(">");
8145 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008146 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008147
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008148 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008149 Builder.AddTypedTextChunk("include_next");
8150 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8151 Builder.AddTextChunk("\"");
8152 Builder.AddPlaceholderChunk("header");
8153 Builder.AddTextChunk("\"");
8154 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008155
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008156 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008157 Builder.AddTypedTextChunk("include_next");
8158 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8159 Builder.AddTextChunk("<");
8160 Builder.AddPlaceholderChunk("header");
8161 Builder.AddTextChunk(">");
8162 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008163
8164 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008165 Builder.AddTypedTextChunk("warning");
8166 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8167 Builder.AddPlaceholderChunk("message");
8168 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008169
8170 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8171 // completions for them. And __include_macros is a Clang-internal extension
8172 // that we don't want to encourage anyone to use.
8173
8174 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8175 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008176
8177 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008178 Results.data(), Results.size());
8179}
8180
8181void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008182 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8183 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008184}
8185
Douglas Gregorec00a262010-08-24 22:20:20 +00008186void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008187 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008188 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008189 IsDefinition ? CodeCompletionContext::CCC_MacroName
8190 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008191 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008192 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008193 CodeCompletionBuilder Builder(Results.getAllocator(),
8194 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008195 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008196 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008197 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008198 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008199 Builder.AddTypedTextChunk(
8200 Builder.getAllocator().CopyString(M->first->getName()));
8201 Results.AddResult(CodeCompletionResult(
8202 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008203 }
8204 Results.ExitScope();
8205 } else if (IsDefinition) {
8206 // FIXME: Can we detect when the user just wrote an include guard above?
8207 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008208
Douglas Gregor0ac41382010-09-23 23:01:17 +00008209 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008210 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008211}
8212
Douglas Gregorec00a262010-08-24 22:20:20 +00008213void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008214 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008215 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008216 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008217
Douglas Gregorec00a262010-08-24 22:20:20 +00008218 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008219 AddMacroResults(PP, Results,
8220 CodeCompleter ? CodeCompleter->loadExternal() : false,
8221 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008222
Fangrui Song050229d2018-11-24 00:14:31 +00008223 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008224 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008225 CodeCompletionBuilder Builder(Results.getAllocator(),
8226 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008227 Builder.AddTypedTextChunk("defined");
8228 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8229 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8230 Builder.AddPlaceholderChunk("macro");
8231 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8232 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008233 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008234
8235 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8236 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008237}
8238
8239void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8240 IdentifierInfo *Macro,
8241 MacroInfo *MacroInfo,
8242 unsigned Argument) {
8243 // FIXME: In the future, we could provide "overload" results, much like we
8244 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008245
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008246 // Now just ignore this. There will be another code-completion callback
8247 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008248}
8249
Sam McCall3d8051a2018-09-18 08:40:41 +00008250// This handles completion inside an #include filename, e.g. #include <foo/ba
8251// We look for the directory "foo" under each directory on the include path,
8252// list its files, and reassemble the appropriate #include.
8253void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8254 // RelDir should use /, but unescaped \ is possible on windows!
8255 // Our completions will normalize to / for simplicity, this case is rare.
8256 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8257 // We need the native slashes for the actual file system interactions.
8258 SmallString<128> NativeRelDir = StringRef(RelDir);
8259 llvm::sys::path::native(NativeRelDir);
8260 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8261
8262 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8263 CodeCompleter->getCodeCompletionTUInfo(),
8264 CodeCompletionContext::CCC_IncludedFile);
8265 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8266
8267 // Helper: adds one file or directory completion result.
8268 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8269 SmallString<64> TypedChunk = Filename;
8270 // Directory completion is up to the slash, e.g. <sys/
8271 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8272 auto R = SeenResults.insert(TypedChunk);
8273 if (R.second) { // New completion
8274 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8275 *R.first = InternedTyped; // Avoid dangling StringRef.
8276 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8277 CodeCompleter->getCodeCompletionTUInfo());
8278 Builder.AddTypedTextChunk(InternedTyped);
8279 // The result is a "Pattern", which is pretty opaque.
8280 // We may want to include the real filename to allow smart ranking.
8281 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8282 }
8283 };
8284
8285 // Helper: scans IncludeDir for nice files, and adds results for each.
8286 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
8287 llvm::SmallString<128> Dir = IncludeDir;
8288 if (!NativeRelDir.empty())
8289 llvm::sys::path::append(Dir, NativeRelDir);
8290
8291 std::error_code EC;
8292 unsigned Count = 0;
8293 for (auto It = FS->dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008294 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008295 if (++Count == 2500) // If we happen to hit a huge directory,
8296 break; // bail out early so we're not too slow.
8297 StringRef Filename = llvm::sys::path::filename(It->path());
8298 switch (It->type()) {
8299 case llvm::sys::fs::file_type::directory_file:
8300 AddCompletion(Filename, /*IsDirectory=*/true);
8301 break;
8302 case llvm::sys::fs::file_type::regular_file:
8303 // Only files that really look like headers. (Except in system dirs).
8304 if (!IsSystem) {
8305 // Header extensions from Types.def, which we can't depend on here.
8306 if (!(Filename.endswith_lower(".h") ||
8307 Filename.endswith_lower(".hh") ||
8308 Filename.endswith_lower(".hpp") ||
8309 Filename.endswith_lower(".inc")))
8310 break;
8311 }
8312 AddCompletion(Filename, /*IsDirectory=*/false);
8313 break;
8314 default:
8315 break;
8316 }
8317 }
8318 };
8319
8320 // Helper: adds results relative to IncludeDir, if possible.
8321 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8322 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008323 switch (IncludeDir.getLookupType()) {
8324 case DirectoryLookup::LT_HeaderMap:
8325 // header maps are not (currently) enumerable.
8326 break;
8327 case DirectoryLookup::LT_NormalDir:
8328 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
8329 break;
8330 case DirectoryLookup::LT_Framework:
8331 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
8332 break;
8333 }
8334 };
8335
8336 // Finally with all our helpers, we can scan the include path.
8337 // Do this in standard order so deduplication keeps the right file.
8338 // (In case we decide to add more details to the results later).
8339 const auto &S = PP.getHeaderSearchInfo();
8340 using llvm::make_range;
8341 if (!Angled) {
8342 // The current directory is on the include path for "quoted" includes.
8343 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8344 if (CurFile && CurFile->getDir())
8345 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
8346 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8347 AddFilesFromDirLookup(D, false);
8348 }
8349 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008350 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008351 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8352 AddFilesFromDirLookup(D, true);
8353
8354 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8355 Results.data(), Results.size());
8356}
8357
Douglas Gregor11583702010-08-25 17:04:25 +00008358void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008359 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008360 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8361 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008362}
8363
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008364void Sema::CodeCompleteAvailabilityPlatformName() {
8365 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8366 CodeCompleter->getCodeCompletionTUInfo(),
8367 CodeCompletionContext::CCC_Other);
8368 Results.EnterNewScope();
8369 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8370 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8371 Results.AddResult(CodeCompletionResult(Platform));
8372 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8373 Twine(Platform) + "ApplicationExtension")));
8374 }
8375 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008376 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8377 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008378}
8379
Fangrui Song050229d2018-11-24 00:14:31 +00008380void Sema::GatherGlobalCodeCompletions(
8381 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8382 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008383 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8384 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008385 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008386 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008387 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008388 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8389 Consumer,
8390 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008391 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008392
Douglas Gregorb14904c2010-08-13 22:48:40 +00008393 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008394 AddMacroResults(PP, Builder,
8395 CodeCompleter ? CodeCompleter->loadExternal() : false,
8396 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008397
Douglas Gregorb14904c2010-08-13 22:48:40 +00008398 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008399 Results.insert(Results.end(), Builder.data(),
8400 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008401}