blob: 2acc896d53d71bd2d29997984b6706df66fd45a5 [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000013#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000017#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000018#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000019#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000020#include "clang/Lex/MacroInfo.h"
21#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000022#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "clang/Sema/Lookup.h"
24#include "clang/Sema/Overload.h"
25#include "clang/Sema/Scope.h"
26#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000027#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000028#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000029#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000030#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000031#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000032#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000033#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000034#include "llvm/ADT/Twine.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000035#include <list>
36#include <map>
37#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000038
39using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000040using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000041
Douglas Gregor3545ff42009-09-21 16:56:56 +000042namespace {
43 /// \brief A container of code-completion results.
44 class ResultBuilder {
45 public:
46 /// \brief The type of a name-lookup filter, which can be provided to the
47 /// name-lookup routines to specify which declarations should be included in
48 /// the result set (when it returns true) and which declarations should be
49 /// filtered out (returns false).
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000050 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000051
John McCall276321a2010-08-25 06:19:51 +000052 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +000053
54 private:
55 /// \brief The actual results we have found.
56 std::vector<Result> Results;
57
58 /// \brief A record of all of the declarations we have found and placed
59 /// into the result set, used to ensure that no declaration ever gets into
60 /// the result set twice.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000061 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Douglas Gregor3545ff42009-09-21 16:56:56 +000062
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000063 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000064
65 /// \brief An entry in the shadow map, which is optimized to store
66 /// a single (declaration, index) mapping (the common case) but
67 /// can also store a list of (declaration, index) mappings.
68 class ShadowMapEntry {
Chris Lattner0e62c1c2011-07-23 10:55:15 +000069 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000070
71 /// \brief Contains either the solitary NamedDecl * or a vector
72 /// of (declaration, index) pairs.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000073 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000074
75 /// \brief When the entry contains a single declaration, this is
76 /// the index associated with that entry.
77 unsigned SingleDeclIndex;
78
79 public:
80 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
81
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000082 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000083 if (DeclOrVector.isNull()) {
84 // 0 - > 1 elements: just set the single element information.
85 DeclOrVector = ND;
86 SingleDeclIndex = Index;
87 return;
88 }
89
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +000090 if (const NamedDecl *PrevND =
91 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +000092 // 1 -> 2 elements: create the vector of results and push in the
93 // existing declaration.
94 DeclIndexPairVector *Vec = new DeclIndexPairVector;
95 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
96 DeclOrVector = Vec;
97 }
98
99 // Add the new element to the end of the vector.
100 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
101 DeclIndexPair(ND, Index));
102 }
103
104 void Destroy() {
105 if (DeclIndexPairVector *Vec
106 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
107 delete Vec;
Craig Topperc3ec1492014-05-26 06:22:03 +0000108 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000109 }
110 }
111
112 // Iteration.
113 class iterator;
114 iterator begin() const;
115 iterator end() const;
116 };
117
Douglas Gregor3545ff42009-09-21 16:56:56 +0000118 /// \brief A mapping from declaration names to the declarations that have
119 /// this name within a particular scope and their index within the list of
120 /// results.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000121 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000122
123 /// \brief The semantic analysis object for which results are being
124 /// produced.
125 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000126
127 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000128 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000129
130 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000131
132 /// \brief If non-NULL, a filter function used to remove any code-completion
133 /// results that are not desirable.
134 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000135
136 /// \brief Whether we should allow declarations as
137 /// nested-name-specifiers that would otherwise be filtered out.
138 bool AllowNestedNameSpecifiers;
139
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000140 /// \brief If set, the type that we would prefer our resulting value
141 /// declarations to have.
142 ///
143 /// Closely matching the preferred type gives a boost to a result's
144 /// priority.
145 CanQualType PreferredType;
146
Douglas Gregor3545ff42009-09-21 16:56:56 +0000147 /// \brief A list of shadow maps, which is used to model name hiding at
148 /// different levels of, e.g., the inheritance hierarchy.
149 std::list<ShadowMap> ShadowMaps;
150
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000151 /// \brief If we're potentially referring to a C++ member function, the set
152 /// of qualifiers applied to the object type.
153 Qualifiers ObjectTypeQualifiers;
154
155 /// \brief Whether the \p ObjectTypeQualifiers field is active.
156 bool HasObjectTypeQualifiers;
157
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000158 /// \brief The selector that we prefer.
159 Selector PreferredSelector;
160
Douglas Gregor05fcf842010-11-02 20:36:02 +0000161 /// \brief The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000162 CodeCompletionContext CompletionContext;
163
James Dennett596e4752012-06-14 03:11:41 +0000164 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000165 /// object.
166 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000167
Douglas Gregor50832e02010-09-20 22:39:41 +0000168 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000169
Douglas Gregor0212fd72010-09-21 16:06:22 +0000170 void MaybeAddConstructorResults(Result R);
171
Douglas Gregor3545ff42009-09-21 16:56:56 +0000172 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000173 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000174 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000175 const CodeCompletionContext &CompletionContext,
Craig Topperc3ec1492014-05-26 06:22:03 +0000176 LookupFilter Filter = nullptr)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000177 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
178 Filter(Filter),
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000179 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000180 CompletionContext(CompletionContext),
Craig Topperc3ec1492014-05-26 06:22:03 +0000181 ObjCImplementation(nullptr)
Douglas Gregor05fcf842010-11-02 20:36:02 +0000182 {
183 // If this is an Objective-C instance method definition, dig out the
184 // corresponding implementation.
185 switch (CompletionContext.getKind()) {
186 case CodeCompletionContext::CCC_Expression:
187 case CodeCompletionContext::CCC_ObjCMessageReceiver:
188 case CodeCompletionContext::CCC_ParenthesizedExpression:
189 case CodeCompletionContext::CCC_Statement:
190 case CodeCompletionContext::CCC_Recovery:
191 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
192 if (Method->isInstanceMethod())
193 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
194 ObjCImplementation = Interface->getImplementation();
195 break;
196
197 default:
198 break;
199 }
200 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000201
202 /// \brief Determine the priority for a reference to the given declaration.
203 unsigned getBasePriority(const NamedDecl *D);
204
Douglas Gregorf64acca2010-05-25 21:41:55 +0000205 /// \brief Whether we should include code patterns in the completion
206 /// results.
207 bool includeCodePatterns() const {
208 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000209 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000210 }
211
Douglas Gregor3545ff42009-09-21 16:56:56 +0000212 /// \brief Set the filter used for code-completion results.
213 void setFilter(LookupFilter Filter) {
214 this->Filter = Filter;
215 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000216
217 Result *data() { return Results.empty()? nullptr : &Results.front(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000218 unsigned size() const { return Results.size(); }
219 bool empty() const { return Results.empty(); }
220
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000221 /// \brief Specify the preferred type.
222 void setPreferredType(QualType T) {
223 PreferredType = SemaRef.Context.getCanonicalType(T);
224 }
225
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000226 /// \brief Set the cv-qualifiers on the object type, for us in filtering
227 /// calls to member functions.
228 ///
229 /// When there are qualifiers in this set, they will be used to filter
230 /// out member functions that aren't available (because there will be a
231 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
232 /// match.
233 void setObjectTypeQualifiers(Qualifiers Quals) {
234 ObjectTypeQualifiers = Quals;
235 HasObjectTypeQualifiers = true;
236 }
237
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000238 /// \brief Set the preferred selector.
239 ///
240 /// When an Objective-C method declaration result is added, and that
241 /// method's selector matches this preferred selector, we give that method
242 /// a slight priority boost.
243 void setPreferredSelector(Selector Sel) {
244 PreferredSelector = Sel;
245 }
Douglas Gregor05fcf842010-11-02 20:36:02 +0000246
Douglas Gregor50832e02010-09-20 22:39:41 +0000247 /// \brief Retrieve the code-completion context for which results are
248 /// being collected.
249 const CodeCompletionContext &getCompletionContext() const {
250 return CompletionContext;
251 }
252
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000253 /// \brief Specify whether nested-name-specifiers are allowed.
254 void allowNestedNameSpecifiers(bool Allow = true) {
255 AllowNestedNameSpecifiers = Allow;
256 }
257
Douglas Gregor74661272010-09-21 00:03:25 +0000258 /// \brief Return the semantic analysis object for which we are collecting
259 /// code completion results.
260 Sema &getSema() const { return SemaRef; }
261
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000262 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000263 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000264
265 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000266
Douglas Gregor7c208612010-01-14 00:20:49 +0000267 /// \brief Determine whether the given declaration is at all interesting
268 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000269 ///
270 /// \param ND the declaration that we are inspecting.
271 ///
272 /// \param AsNestedNameSpecifier will be set true if this declaration is
273 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000274 bool isInterestingDecl(const NamedDecl *ND,
275 bool &AsNestedNameSpecifier) const;
Douglas Gregore0717ab2010-01-14 00:41:07 +0000276
277 /// \brief Check whether the result is hidden by the Hiding declaration.
278 ///
279 /// \returns true if the result is hidden and cannot be found, false if
280 /// the hidden result could still be found. When false, \p R may be
281 /// modified to describe how the result can be found (e.g., via extra
282 /// qualification).
283 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000284 const NamedDecl *Hiding);
Douglas Gregore0717ab2010-01-14 00:41:07 +0000285
Douglas Gregor3545ff42009-09-21 16:56:56 +0000286 /// \brief Add a new result to this result set (if it isn't already in one
287 /// of the shadow maps), or replace an existing result (for, e.g., a
288 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000289 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000290 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000291 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000292 /// \param CurContext the context in which this result will be named.
Craig Topperc3ec1492014-05-26 06:22:03 +0000293 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
294
Douglas Gregorc580c522010-01-14 01:09:38 +0000295 /// \brief Add a new result to this result set, where we already know
Yaron Keren8fbe43982014-11-14 18:33:42 +0000296 /// the hiding declaration (if any).
Douglas Gregorc580c522010-01-14 01:09:38 +0000297 ///
298 /// \param R the result to add (if it is unique).
299 ///
300 /// \param CurContext the context in which this result will be named.
301 ///
302 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000303 ///
304 /// \param InBaseClass whether the result was found in a base
305 /// class of the searched context.
306 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
307 bool InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +0000308
Douglas Gregor78a21012010-01-14 16:01:26 +0000309 /// \brief Add a new non-declaration result to this result set.
310 void AddResult(Result R);
311
Douglas Gregor3545ff42009-09-21 16:56:56 +0000312 /// \brief Enter into a new scope.
313 void EnterNewScope();
314
315 /// \brief Exit from the current scope.
316 void ExitScope();
317
Douglas Gregorbaf69612009-11-18 04:19:12 +0000318 /// \brief Ignore this declaration, if it is seen again.
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +0000319 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregorbaf69612009-11-18 04:19:12 +0000320
Douglas Gregor3545ff42009-09-21 16:56:56 +0000321 /// \name Name lookup predicates
322 ///
323 /// These predicates can be passed to the name lookup functions to filter the
324 /// results of name lookup. All of the predicates have the same type, so that
325 ///
326 //@{
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000327 bool IsOrdinaryName(const NamedDecl *ND) const;
328 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
329 bool IsIntegralConstantValue(const NamedDecl *ND) const;
330 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
331 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
332 bool IsEnum(const NamedDecl *ND) const;
333 bool IsClassOrStruct(const NamedDecl *ND) const;
334 bool IsUnion(const NamedDecl *ND) const;
335 bool IsNamespace(const NamedDecl *ND) const;
336 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
337 bool IsType(const NamedDecl *ND) const;
338 bool IsMember(const NamedDecl *ND) const;
339 bool IsObjCIvar(const NamedDecl *ND) const;
340 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
341 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
342 bool IsObjCCollection(const NamedDecl *ND) const;
343 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000344 //@}
345 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000346}
Douglas Gregor3545ff42009-09-21 16:56:56 +0000347
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000348class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000349 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000350 unsigned SingleDeclIndex;
351
352public:
353 typedef DeclIndexPair value_type;
354 typedef value_type reference;
355 typedef std::ptrdiff_t difference_type;
356 typedef std::input_iterator_tag iterator_category;
357
358 class pointer {
359 DeclIndexPair Value;
360
361 public:
362 pointer(const DeclIndexPair &Value) : Value(Value) { }
363
364 const DeclIndexPair *operator->() const {
365 return &Value;
366 }
367 };
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)
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000372 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
373
374 iterator(const DeclIndexPair *Iterator)
375 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
376
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
384 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
385 ++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
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000400 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000401 }
402
403 pointer operator->() const {
404 return pointer(**this);
405 }
406
407 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000408 return X.DeclOrIterator.getOpaqueValue()
409 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000410 X.SingleDeclIndex == Y.SingleDeclIndex;
411 }
412
413 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000414 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000415 }
416};
417
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000418ResultBuilder::ShadowMapEntry::iterator
419ResultBuilder::ShadowMapEntry::begin() const {
420 if (DeclOrVector.isNull())
421 return iterator();
422
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000423 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000424 return iterator(ND, SingleDeclIndex);
425
426 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
427}
428
429ResultBuilder::ShadowMapEntry::iterator
430ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000431 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000432 return iterator();
433
434 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
435}
436
Douglas Gregor2af2f672009-09-21 20:12:40 +0000437/// \brief Compute the qualification required to get from the current context
438/// (\p CurContext) to the target context (\p TargetContext).
439///
440/// \param Context the AST context in which the qualification will be used.
441///
442/// \param CurContext the context where an entity is being named, which is
443/// typically based on the current scope.
444///
445/// \param TargetContext the context in which the named entity actually
446/// resides.
447///
448/// \returns a nested name specifier that refers into the target context, or
449/// NULL if no qualification is needed.
450static NestedNameSpecifier *
451getRequiredQualification(ASTContext &Context,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000452 const DeclContext *CurContext,
453 const DeclContext *TargetContext) {
454 SmallVector<const DeclContext *, 4> TargetParents;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000455
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000456 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000457 CommonAncestor && !CommonAncestor->Encloses(CurContext);
458 CommonAncestor = CommonAncestor->getLookupParent()) {
459 if (CommonAncestor->isTransparentContext() ||
460 CommonAncestor->isFunctionOrMethod())
461 continue;
462
463 TargetParents.push_back(CommonAncestor);
464 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000465
466 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000467 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000468 const DeclContext *Parent = TargetParents.pop_back_val();
469
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000470 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000471 if (!Namespace->getIdentifier())
472 continue;
473
Douglas Gregor2af2f672009-09-21 20:12:40 +0000474 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000475 }
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000476 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000477 Result = NestedNameSpecifier::Create(Context, Result,
478 false,
479 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor9eb77012009-11-07 00:00:49 +0000480 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000481 return Result;
482}
483
Alp Toker034bbd52014-06-30 01:33:53 +0000484/// Determine whether \p Id is a name reserved for the implementation (C99
485/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000486static bool isReservedName(const IdentifierInfo *Id,
487 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000488 if (Id->getLength() < 2)
489 return false;
490 const char *Name = Id->getNameStart();
491 return Name[0] == '_' &&
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000492 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z' &&
493 !doubleUnderscoreOnly));
494}
495
496// Some declarations have reserved names that we don't want to ever show.
497// Filter out names reserved for the implementation if they come from a
498// system header.
499static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
500 const IdentifierInfo *Id = ND->getIdentifier();
501 if (!Id)
502 return false;
503
504 // Ignore reserved names for compiler provided decls.
505 if (isReservedName(Id) && ND->getLocation().isInvalid())
506 return true;
507
508 // For system headers ignore only double-underscore names.
509 // This allows for system headers providing private symbols with a single
510 // underscore.
511 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
512 SemaRef.SourceMgr.isInSystemHeader(
513 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
514 return true;
515
516 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000517}
518
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000519bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000520 bool &AsNestedNameSpecifier) const {
521 AsNestedNameSpecifier = false;
522
Richard Smithf2005d32015-12-29 23:34:32 +0000523 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000524 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000525
526 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000527 if (!ND->getDeclName())
528 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000529
530 // Friend declarations and declarations introduced due to friends are never
531 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000532 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000533 return false;
534
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000535 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000536 if (isa<ClassTemplateSpecializationDecl>(ND) ||
537 isa<ClassTemplatePartialSpecializationDecl>(ND))
538 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000539
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000540 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000541 if (isa<UsingDecl>(ND))
542 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000543
544 if (shouldIgnoreDueToReservedName(ND, SemaRef))
545 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000546
Douglas Gregor59cab552010-08-16 23:05:20 +0000547 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Richard Smithf2005d32015-12-29 23:34:32 +0000548 (isa<NamespaceDecl>(ND) &&
Douglas Gregor59cab552010-08-16 23:05:20 +0000549 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000550 Filter != &ResultBuilder::IsNamespaceOrAlias &&
Craig Topperc3ec1492014-05-26 06:22:03 +0000551 Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000552 AsNestedNameSpecifier = true;
553
Douglas Gregor3545ff42009-09-21 16:56:56 +0000554 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000555 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000556 // Check whether it is interesting as a nested-name-specifier.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000557 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000558 IsNestedNameSpecifier(ND) &&
559 (Filter != &ResultBuilder::IsMember ||
560 (isa<CXXRecordDecl>(ND) &&
561 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
562 AsNestedNameSpecifier = true;
563 return true;
564 }
565
Douglas Gregor7c208612010-01-14 00:20:49 +0000566 return false;
Douglas Gregor59cab552010-08-16 23:05:20 +0000567 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000568 // ... then it must be interesting!
569 return true;
570}
571
Douglas Gregore0717ab2010-01-14 00:41:07 +0000572bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000573 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000574 // In C, there is no way to refer to a hidden name.
575 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
576 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000577 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000578 return true;
579
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000580 const DeclContext *HiddenCtx =
581 R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregore0717ab2010-01-14 00:41:07 +0000582
583 // There is no way to qualify a name declared in a function or method.
584 if (HiddenCtx->isFunctionOrMethod())
585 return true;
586
Sebastian Redl50c68252010-08-31 00:36:30 +0000587 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000588 return true;
589
590 // We can refer to the result with the appropriate qualification. Do it.
591 R.Hidden = true;
592 R.QualifierIsInformative = false;
593
594 if (!R.Qualifier)
595 R.Qualifier = getRequiredQualification(SemaRef.Context,
596 CurContext,
597 R.Declaration->getDeclContext());
598 return false;
599}
600
Douglas Gregor95887f92010-07-08 23:20:03 +0000601/// \brief A simplified classification of types used to determine whether two
602/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000603SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000604 switch (T->getTypeClass()) {
605 case Type::Builtin:
606 switch (cast<BuiltinType>(T)->getKind()) {
607 case BuiltinType::Void:
608 return STC_Void;
609
610 case BuiltinType::NullPtr:
611 return STC_Pointer;
612
613 case BuiltinType::Overload:
614 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000615 return STC_Other;
616
617 case BuiltinType::ObjCId:
618 case BuiltinType::ObjCClass:
619 case BuiltinType::ObjCSel:
620 return STC_ObjectiveC;
621
622 default:
623 return STC_Arithmetic;
624 }
David Blaikie8a40f702012-01-17 06:56:22 +0000625
Douglas Gregor95887f92010-07-08 23:20:03 +0000626 case Type::Complex:
627 return STC_Arithmetic;
628
629 case Type::Pointer:
630 return STC_Pointer;
631
632 case Type::BlockPointer:
633 return STC_Block;
634
635 case Type::LValueReference:
636 case Type::RValueReference:
637 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
638
639 case Type::ConstantArray:
640 case Type::IncompleteArray:
641 case Type::VariableArray:
642 case Type::DependentSizedArray:
643 return STC_Array;
644
645 case Type::DependentSizedExtVector:
646 case Type::Vector:
647 case Type::ExtVector:
648 return STC_Arithmetic;
649
650 case Type::FunctionProto:
651 case Type::FunctionNoProto:
652 return STC_Function;
653
654 case Type::Record:
655 return STC_Record;
656
657 case Type::Enum:
658 return STC_Arithmetic;
659
660 case Type::ObjCObject:
661 case Type::ObjCInterface:
662 case Type::ObjCObjectPointer:
663 return STC_ObjectiveC;
664
665 default:
666 return STC_Other;
667 }
668}
669
670/// \brief Get the type that a given expression will have if this declaration
671/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000672QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000673 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
674
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000675 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000676 return C.getTypeDeclType(Type);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000677 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000678 return C.getObjCInterfaceType(Iface);
679
680 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000681 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000682 T = Function->getCallResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000683 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000684 T = Method->getSendResultType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000685 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000686 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000687 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000688 T = Property->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000689 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000690 T = Value->getType();
691 else
692 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000693
694 // Dig through references, function pointers, and block pointers to
695 // get down to the likely type of an expression when the entity is
696 // used.
697 do {
698 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
699 T = Ref->getPointeeType();
700 continue;
701 }
702
703 if (const PointerType *Pointer = T->getAs<PointerType>()) {
704 if (Pointer->getPointeeType()->isFunctionType()) {
705 T = Pointer->getPointeeType();
706 continue;
707 }
708
709 break;
710 }
711
712 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
713 T = Block->getPointeeType();
714 continue;
715 }
716
717 if (const FunctionType *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000718 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000719 continue;
720 }
721
722 break;
723 } while (true);
724
725 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000726}
727
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000728unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
729 if (!ND)
730 return CCP_Unlikely;
731
732 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000733 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
734 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000735 // _cmd is relatively rare
736 if (const ImplicitParamDecl *ImplicitParam =
737 dyn_cast<ImplicitParamDecl>(ND))
738 if (ImplicitParam->getIdentifier() &&
739 ImplicitParam->getIdentifier()->isStr("_cmd"))
740 return CCP_ObjC_cmd;
741
742 return CCP_LocalDeclaration;
743 }
Richard Smith541b38b2013-09-20 01:15:31 +0000744
745 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000746 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
747 // Explicit destructor calls are very rare.
748 if (isa<CXXDestructorDecl>(ND))
749 return CCP_Unlikely;
750 // Explicit operator and conversion function calls are also very rare.
751 auto DeclNameKind = ND->getDeclName().getNameKind();
752 if (DeclNameKind == DeclarationName::CXXOperatorName ||
753 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
754 DeclNameKind == DeclarationName::CXXConversionFunctionName)
755 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000756 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000757 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000758
759 // Content-based decisions.
760 if (isa<EnumConstantDecl>(ND))
761 return CCP_Constant;
762
Douglas Gregor52e0de42013-01-31 05:03:46 +0000763 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
764 // message receiver, or parenthesized expression context. There, it's as
765 // likely that the user will want to write a type as other declarations.
766 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
767 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
768 CompletionContext.getKind()
769 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
770 CompletionContext.getKind()
771 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000772 return CCP_Type;
773
774 return CCP_Declaration;
775}
776
Douglas Gregor50832e02010-09-20 22:39:41 +0000777void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
778 // If this is an Objective-C method declaration whose selector matches our
779 // preferred selector, give it a priority boost.
780 if (!PreferredSelector.isNull())
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000781 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000782 if (PreferredSelector == Method->getSelector())
783 R.Priority += CCD_SelectorMatch;
Douglas Gregor5fb901d2010-09-20 23:11:55 +0000784
Douglas Gregor50832e02010-09-20 22:39:41 +0000785 // If we have a preferred type, adjust the priority for results with exactly-
786 // matching or nearly-matching types.
787 if (!PreferredType.isNull()) {
788 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
789 if (!T.isNull()) {
790 CanQualType TC = SemaRef.Context.getCanonicalType(T);
791 // Check for exactly-matching types (modulo qualifiers).
792 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
793 R.Priority /= CCF_ExactTypeMatch;
794 // Check for nearly-matching types, based on classification of each.
795 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000796 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000797 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
798 R.Priority /= CCF_SimilarTypeMatch;
799 }
800 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000801}
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;
807
808 ASTContext &Context = SemaRef.Context;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000809 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000810 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000811 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000812 Record = ClassTemplate->getTemplatedDecl();
813 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
814 // Skip specializations and partial specializations.
815 if (isa<ClassTemplateSpecializationDecl>(Record))
816 return;
817 } else {
818 // There are no constructors here.
819 return;
820 }
821
822 Record = Record->getDefinition();
823 if (!Record)
824 return;
825
826
827 QualType RecordTy = Context.getTypeDeclType(Record);
828 DeclarationName ConstructorName
829 = Context.DeclarationNames.getCXXConstructorName(
830 Context.getCanonicalType(RecordTy));
Richard Smithcf4bdde2015-02-21 02:45:19 +0000831 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
832 for (DeclContext::lookup_iterator I = Ctors.begin(),
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000833 E = Ctors.end();
834 I != E; ++I) {
David Blaikieff7d47a2012-12-19 00:45:41 +0000835 R.Declaration = *I;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000836 R.CursorKind = getCursorKindForDecl(R.Declaration);
837 Results.push_back(R);
838 }
839}
840
Douglas Gregor7c208612010-01-14 00:20:49 +0000841void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
842 assert(!ShadowMaps.empty() && "Must enter into a results scope");
843
844 if (R.Kind != Result::RK_Declaration) {
845 // For non-declaration results, just add the result.
846 Results.push_back(R);
847 return;
848 }
849
850 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000851 if (const UsingShadowDecl *Using =
852 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000853 MaybeAddResult(Result(Using->getTargetDecl(),
854 getBasePriority(Using->getTargetDecl()),
855 R.Qualifier),
856 CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000857 return;
858 }
859
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000860 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000861 unsigned IDNS = CanonDecl->getIdentifierNamespace();
862
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000863 bool AsNestedNameSpecifier = false;
864 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000865 return;
866
Douglas Gregor0212fd72010-09-21 16:06:22 +0000867 // C++ constructors are never found by name lookup.
868 if (isa<CXXConstructorDecl>(R.Declaration))
869 return;
870
Douglas Gregor3545ff42009-09-21 16:56:56 +0000871 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000872 ShadowMapEntry::iterator I, IEnd;
873 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
874 if (NamePos != SMap.end()) {
875 I = NamePos->second.begin();
876 IEnd = NamePos->second.end();
877 }
878
879 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000880 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000881 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000882 if (ND->getCanonicalDecl() == CanonDecl) {
883 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000884 Results[Index].Declaration = R.Declaration;
885
Douglas Gregor3545ff42009-09-21 16:56:56 +0000886 // We're done.
887 return;
888 }
889 }
890
891 // This is a new declaration in this scope. However, check whether this
892 // declaration name is hidden by a similarly-named declaration in an outer
893 // scope.
894 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
895 --SMEnd;
896 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000897 ShadowMapEntry::iterator I, IEnd;
898 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
899 if (NamePos != SM->end()) {
900 I = NamePos->second.begin();
901 IEnd = NamePos->second.end();
902 }
903 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000904 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000905 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000906 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
907 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000908 continue;
909
910 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000911 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000912 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000913 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000914 continue;
915
916 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000917 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000918 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000919
920 break;
921 }
922 }
923
924 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000925 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000926 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000927
Douglas Gregore412a5a2009-09-23 22:26:46 +0000928 // If the filter is for nested-name-specifiers, then this result starts a
929 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000930 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000931 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000932 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregor50832e02010-09-20 22:39:41 +0000933 } else
934 AdjustResultPriorityForDecl(R);
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000935
Douglas Gregor5bf52692009-09-22 23:15:58 +0000936 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000937 if (R.QualifierIsInformative && !R.Qualifier &&
938 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000939 const DeclContext *Ctx = R.Declaration->getDeclContext();
940 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000941 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
942 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000943 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +0000944 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
945 false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000946 else
947 R.QualifierIsInformative = false;
948 }
Douglas Gregore412a5a2009-09-23 22:26:46 +0000949
Douglas Gregor3545ff42009-09-21 16:56:56 +0000950 // Insert this result into the set of results and into the current shadow
951 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000952 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000953 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000954
955 if (!AsNestedNameSpecifier)
956 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000957}
958
Douglas Gregorc580c522010-01-14 01:09:38 +0000959void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000960 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000961 if (R.Kind != Result::RK_Declaration) {
962 // For non-declaration results, just add the result.
963 Results.push_back(R);
964 return;
965 }
966
Douglas Gregorc580c522010-01-14 01:09:38 +0000967 // Look through using declarations.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000968 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000969 AddResult(Result(Using->getTargetDecl(),
970 getBasePriority(Using->getTargetDecl()),
971 R.Qualifier),
972 CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000973 return;
974 }
975
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000976 bool AsNestedNameSpecifier = false;
977 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000978 return;
979
Douglas Gregor0212fd72010-09-21 16:06:22 +0000980 // C++ constructors are never found by name lookup.
981 if (isa<CXXConstructorDecl>(R.Declaration))
982 return;
983
Douglas Gregorc580c522010-01-14 01:09:38 +0000984 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
985 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000986
Douglas Gregorc580c522010-01-14 01:09:38 +0000987 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000988 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +0000989 return;
990
991 // If the filter is for nested-name-specifiers, then this result starts a
992 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000993 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +0000994 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000995 R.Priority = CCP_NestedNameSpecifier;
996 }
Douglas Gregor09bbc652010-01-14 15:47:35 +0000997 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
998 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl50c68252010-08-31 00:36:30 +0000999 ->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001000 R.QualifierIsInformative = true;
1001
Douglas Gregorc580c522010-01-14 01:09:38 +00001002 // If this result is supposed to have an informative qualifier, add one.
1003 if (R.QualifierIsInformative && !R.Qualifier &&
1004 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001005 const DeclContext *Ctx = R.Declaration->getDeclContext();
1006 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001007 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr,
1008 Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001009 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Craig Topperc3ec1492014-05-26 06:22:03 +00001010 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, nullptr, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +00001011 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001012 else
1013 R.QualifierIsInformative = false;
1014 }
1015
Douglas Gregora2db7932010-05-26 22:00:08 +00001016 // Adjust the priority if this result comes from a base class.
1017 if (InBaseClass)
1018 R.Priority += CCD_InBaseClass;
1019
Douglas Gregor50832e02010-09-20 22:39:41 +00001020 AdjustResultPriorityForDecl(R);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00001021
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001022 if (HasObjectTypeQualifiers)
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001023 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001024 if (Method->isInstance()) {
1025 Qualifiers MethodQuals
1026 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
1027 if (ObjectTypeQualifiers == MethodQuals)
1028 R.Priority += CCD_ObjectQualifierMatch;
1029 else if (ObjectTypeQualifiers - MethodQuals) {
1030 // The method cannot be invoked, because doing so would drop
1031 // qualifiers.
1032 return;
1033 }
1034 }
1035
Douglas Gregorc580c522010-01-14 01:09:38 +00001036 // Insert this result into the set of results.
1037 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +00001038
1039 if (!AsNestedNameSpecifier)
1040 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001041}
1042
Douglas Gregor78a21012010-01-14 16:01:26 +00001043void ResultBuilder::AddResult(Result R) {
1044 assert(R.Kind != Result::RK_Declaration &&
1045 "Declaration results need more context");
1046 Results.push_back(R);
1047}
1048
Douglas Gregor3545ff42009-09-21 16:56:56 +00001049/// \brief Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001050void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001051
1052/// \brief Exit from the current scope.
1053void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001054 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1055 EEnd = ShadowMaps.back().end();
1056 E != EEnd;
1057 ++E)
1058 E->second.Destroy();
1059
Douglas Gregor3545ff42009-09-21 16:56:56 +00001060 ShadowMaps.pop_back();
1061}
1062
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001063/// \brief Determines whether this given declaration will be found by
1064/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001065bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001066 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1067
Richard Smith541b38b2013-09-20 01:15:31 +00001068 // If name lookup finds a local extern declaration, then we are in a
1069 // context where it behaves like an ordinary name.
1070 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001071 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001072 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001073 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001074 if (isa<ObjCIvarDecl>(ND))
1075 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001076 }
1077
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001078 return ND->getIdentifierNamespace() & IDNS;
1079}
1080
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001081/// \brief Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001082/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001083bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001084 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001085 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001086 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001087 // Objective-C interfaces names are not filtered by this method because they
1088 // can be used in a class property expression. We can still filter out
1089 // @class declarations though.
1090 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1091 if (!ID->getDefinition())
1092 return false;
1093 }
1094
Richard Smith541b38b2013-09-20 01:15:31 +00001095 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001096 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001097 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001098 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001099 if (isa<ObjCIvarDecl>(ND))
1100 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001101 }
1102
Douglas Gregor70febae2010-05-28 00:49:12 +00001103 return ND->getIdentifierNamespace() & IDNS;
1104}
1105
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001106bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001107 if (!IsOrdinaryNonTypeName(ND))
1108 return 0;
1109
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001110 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001111 if (VD->getType()->isIntegralOrEnumerationType())
1112 return true;
1113
1114 return false;
1115}
1116
Douglas Gregor70febae2010-05-28 00:49:12 +00001117/// \brief Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001118/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001119bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001120 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1121
Richard Smith541b38b2013-09-20 01:15:31 +00001122 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001123 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001124 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001125
1126 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001127 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1128 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001129}
1130
Douglas Gregor3545ff42009-09-21 16:56:56 +00001131/// \brief Determines whether the given declaration is suitable as the
1132/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001133bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001134 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001135 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001136 ND = ClassTemplate->getTemplatedDecl();
1137
1138 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1139}
1140
1141/// \brief Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001142bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001143 return isa<EnumDecl>(ND);
1144}
1145
1146/// \brief Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001147bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001148 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001149 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001150 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001151
1152 // For purposes of this check, interfaces match too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001153 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001154 return RD->getTagKind() == TTK_Class ||
Joao Matosdc86f942012-08-31 18:45:21 +00001155 RD->getTagKind() == TTK_Struct ||
1156 RD->getTagKind() == TTK_Interface;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001157
1158 return false;
1159}
1160
1161/// \brief Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001162bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001163 // Allow us to find class templates, too.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001164 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001165 ND = ClassTemplate->getTemplatedDecl();
1166
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001167 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001168 return RD->getTagKind() == TTK_Union;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001169
1170 return false;
1171}
1172
1173/// \brief Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001174bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001175 return isa<NamespaceDecl>(ND);
1176}
1177
1178/// \brief Determines whether the given declaration is a namespace or
1179/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001180bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001181 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001182}
1183
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001184/// \brief Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001185bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001186 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001187 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001188}
1189
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001190/// \brief Determines which members of a class should be visible via
1191/// "." or "->". Only value declarations, nested name specifiers, and
1192/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001193bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001194 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001195 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001196 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001197}
1198
Douglas Gregora817a192010-05-27 23:06:34 +00001199static bool isObjCReceiverType(ASTContext &C, QualType T) {
1200 T = C.getCanonicalType(T);
1201 switch (T->getTypeClass()) {
1202 case Type::ObjCObject:
1203 case Type::ObjCInterface:
1204 case Type::ObjCObjectPointer:
1205 return true;
1206
1207 case Type::Builtin:
1208 switch (cast<BuiltinType>(T)->getKind()) {
1209 case BuiltinType::ObjCId:
1210 case BuiltinType::ObjCClass:
1211 case BuiltinType::ObjCSel:
1212 return true;
1213
1214 default:
1215 break;
1216 }
1217 return false;
1218
1219 default:
1220 break;
1221 }
1222
David Blaikiebbafb8a2012-03-11 07:00:24 +00001223 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001224 return false;
1225
1226 // FIXME: We could perform more analysis here to determine whether a
1227 // particular class type has any conversions to Objective-C types. For now,
1228 // just accept all class types.
1229 return T->isDependentType() || T->isRecordType();
1230}
1231
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001232bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001233 QualType T = getDeclUsageType(SemaRef.Context, ND);
1234 if (T.isNull())
1235 return false;
1236
1237 T = SemaRef.Context.getBaseElementType(T);
1238 return isObjCReceiverType(SemaRef.Context, T);
1239}
1240
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001241bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001242 if (IsObjCMessageReceiver(ND))
1243 return true;
1244
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001245 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001246 if (!Var)
1247 return false;
1248
1249 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1250}
1251
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001252bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001253 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1254 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001255 return false;
1256
1257 QualType T = getDeclUsageType(SemaRef.Context, ND);
1258 if (T.isNull())
1259 return false;
1260
1261 T = SemaRef.Context.getBaseElementType(T);
1262 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1263 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001264 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001265}
Douglas Gregora817a192010-05-27 23:06:34 +00001266
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001267bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001268 return false;
1269}
1270
James Dennettf1243872012-06-17 05:33:25 +00001271/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001272/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001273bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001274 return isa<ObjCIvarDecl>(ND);
1275}
1276
Douglas Gregorc580c522010-01-14 01:09:38 +00001277namespace {
1278 /// \brief Visible declaration consumer that adds a code-completion result
1279 /// for each visible declaration.
1280 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1281 ResultBuilder &Results;
1282 DeclContext *CurContext;
1283
1284 public:
1285 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1286 : Results(Results), CurContext(CurContext) { }
Craig Toppere14c0f82014-03-12 04:55:44 +00001287
1288 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1289 bool InBaseClass) override {
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001290 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001291 if (Ctx)
1292 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
Craig Topperc3ec1492014-05-26 06:22:03 +00001293
1294 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
1295 false, Accessible);
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001296 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001297 }
1298 };
Alexander Kornienkoab9db512015-06-22 23:07:51 +00001299}
Douglas Gregorc580c522010-01-14 01:09:38 +00001300
Douglas Gregor3545ff42009-09-21 16:56:56 +00001301/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001302static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001303 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001304 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001305 Results.AddResult(Result("short", CCP_Type));
1306 Results.AddResult(Result("long", CCP_Type));
1307 Results.AddResult(Result("signed", CCP_Type));
1308 Results.AddResult(Result("unsigned", CCP_Type));
1309 Results.AddResult(Result("void", CCP_Type));
1310 Results.AddResult(Result("char", CCP_Type));
1311 Results.AddResult(Result("int", CCP_Type));
1312 Results.AddResult(Result("float", CCP_Type));
1313 Results.AddResult(Result("double", CCP_Type));
1314 Results.AddResult(Result("enum", CCP_Type));
1315 Results.AddResult(Result("struct", CCP_Type));
1316 Results.AddResult(Result("union", CCP_Type));
1317 Results.AddResult(Result("const", CCP_Type));
1318 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001319
Douglas Gregor3545ff42009-09-21 16:56:56 +00001320 if (LangOpts.C99) {
1321 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001322 Results.AddResult(Result("_Complex", CCP_Type));
1323 Results.AddResult(Result("_Imaginary", CCP_Type));
1324 Results.AddResult(Result("_Bool", CCP_Type));
1325 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001326 }
1327
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001328 CodeCompletionBuilder Builder(Results.getAllocator(),
1329 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001330 if (LangOpts.CPlusPlus) {
1331 // C++-specific
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001332 Results.AddResult(Result("bool", CCP_Type +
1333 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001334 Results.AddResult(Result("class", CCP_Type));
1335 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001336
Douglas Gregorf4c33342010-05-28 00:22:41 +00001337 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001338 Builder.AddTypedTextChunk("typename");
1339 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1340 Builder.AddPlaceholderChunk("qualifier");
1341 Builder.AddTextChunk("::");
1342 Builder.AddPlaceholderChunk("name");
1343 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001344
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001345 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001346 Results.AddResult(Result("auto", CCP_Type));
1347 Results.AddResult(Result("char16_t", CCP_Type));
1348 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001349
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001350 Builder.AddTypedTextChunk("decltype");
1351 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1352 Builder.AddPlaceholderChunk("expression");
1353 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1354 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001355 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001356 } else
1357 Results.AddResult(Result("__auto_type", CCP_Type));
1358
Douglas Gregor3545ff42009-09-21 16:56:56 +00001359 // GNU extensions
1360 if (LangOpts.GNUMode) {
1361 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001362 // Results.AddResult(Result("_Decimal32"));
1363 // Results.AddResult(Result("_Decimal64"));
1364 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001365
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001366 Builder.AddTypedTextChunk("typeof");
1367 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1368 Builder.AddPlaceholderChunk("expression");
1369 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001370
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001371 Builder.AddTypedTextChunk("typeof");
1372 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1373 Builder.AddPlaceholderChunk("type");
1374 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1375 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001376 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001377
1378 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001379 Results.AddResult(Result("_Nonnull", CCP_Type));
1380 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1381 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001382}
1383
John McCallfaf5fb42010-08-26 23:41:50 +00001384static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001385 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001386 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001387 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001388 // Note: we don't suggest either "auto" or "register", because both
1389 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1390 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001391 Results.AddResult(Result("extern"));
1392 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001393
1394 if (LangOpts.CPlusPlus11) {
1395 CodeCompletionAllocator &Allocator = Results.getAllocator();
1396 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1397
1398 // alignas
1399 Builder.AddTypedTextChunk("alignas");
1400 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1401 Builder.AddPlaceholderChunk("expression");
1402 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1403 Results.AddResult(Result(Builder.TakeString()));
1404
1405 Results.AddResult(Result("constexpr"));
1406 Results.AddResult(Result("thread_local"));
1407 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001408}
1409
John McCallfaf5fb42010-08-26 23:41:50 +00001410static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001411 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001412 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001413 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001414 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001415 case Sema::PCC_Class:
1416 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001417 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001418 Results.AddResult(Result("explicit"));
1419 Results.AddResult(Result("friend"));
1420 Results.AddResult(Result("mutable"));
1421 Results.AddResult(Result("virtual"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001422 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001423 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001424
John McCallfaf5fb42010-08-26 23:41:50 +00001425 case Sema::PCC_ObjCInterface:
1426 case Sema::PCC_ObjCImplementation:
1427 case Sema::PCC_Namespace:
1428 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001429 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001430 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001431 break;
1432
John McCallfaf5fb42010-08-26 23:41:50 +00001433 case Sema::PCC_ObjCInstanceVariableList:
1434 case Sema::PCC_Expression:
1435 case Sema::PCC_Statement:
1436 case Sema::PCC_ForInit:
1437 case Sema::PCC_Condition:
1438 case Sema::PCC_RecoveryInFunction:
1439 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001440 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001441 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001442 break;
1443 }
1444}
1445
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001446static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1447static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1448static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001449 ResultBuilder &Results,
1450 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001451static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001452 ResultBuilder &Results,
1453 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001454static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001455 ResultBuilder &Results,
1456 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001457static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001458
Douglas Gregorf4c33342010-05-28 00:22:41 +00001459static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001460 CodeCompletionBuilder Builder(Results.getAllocator(),
1461 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001462 Builder.AddTypedTextChunk("typedef");
1463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1464 Builder.AddPlaceholderChunk("type");
1465 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1466 Builder.AddPlaceholderChunk("name");
1467 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001468}
1469
John McCallfaf5fb42010-08-26 23:41:50 +00001470static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001471 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001472 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001473 case Sema::PCC_Namespace:
1474 case Sema::PCC_Class:
1475 case Sema::PCC_ObjCInstanceVariableList:
1476 case Sema::PCC_Template:
1477 case Sema::PCC_MemberTemplate:
1478 case Sema::PCC_Statement:
1479 case Sema::PCC_RecoveryInFunction:
1480 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001481 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001482 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001483 return true;
1484
John McCallfaf5fb42010-08-26 23:41:50 +00001485 case Sema::PCC_Expression:
1486 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001487 return LangOpts.CPlusPlus;
1488
1489 case Sema::PCC_ObjCInterface:
1490 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001491 return false;
1492
John McCallfaf5fb42010-08-26 23:41:50 +00001493 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001494 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001495 }
David Blaikie8a40f702012-01-17 06:56:22 +00001496
1497 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001498}
1499
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001500static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1501 const Preprocessor &PP) {
1502 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001503 Policy.AnonymousTagLocations = false;
1504 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001505 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001506 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001507 return Policy;
1508}
1509
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001510/// \brief Retrieve a printing policy suitable for code completion.
1511static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1512 return getCompletionPrintingPolicy(S.Context, S.PP);
1513}
1514
Douglas Gregore5c79d52011-10-18 21:20:17 +00001515/// \brief Retrieve the string representation of the given type as a string
1516/// that has the appropriate lifetime for code completion.
1517///
1518/// This routine provides a fast path where we provide constant strings for
1519/// common type names.
1520static const char *GetCompletionTypeString(QualType T,
1521 ASTContext &Context,
1522 const PrintingPolicy &Policy,
1523 CodeCompletionAllocator &Allocator) {
1524 if (!T.getLocalQualifiers()) {
1525 // Built-in type names are constant strings.
1526 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001527 return BT->getNameAsCString(Policy);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001528
1529 // Anonymous tag types are constant strings.
1530 if (const TagType *TagT = dyn_cast<TagType>(T))
1531 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001532 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001533 switch (Tag->getTagKind()) {
1534 case TTK_Struct: return "struct <anonymous>";
Joao Matosdc86f942012-08-31 18:45:21 +00001535 case TTK_Interface: return "__interface <anonymous>";
1536 case TTK_Class: return "class <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001537 case TTK_Union: return "union <anonymous>";
1538 case TTK_Enum: return "enum <anonymous>";
1539 }
1540 }
1541 }
1542
1543 // Slow path: format the type as a string.
1544 std::string Result;
1545 T.getAsStringInternal(Result, Policy);
1546 return Allocator.CopyString(Result);
1547}
1548
Douglas Gregord8c61782012-02-15 15:34:24 +00001549/// \brief Add a completion for "this", if we're in a member function.
1550static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1551 QualType ThisTy = S.getCurrentThisType();
1552 if (ThisTy.isNull())
1553 return;
1554
1555 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001556 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001557 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1558 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1559 S.Context,
1560 Policy,
1561 Allocator));
1562 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001563 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001564}
1565
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001566static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1567 ResultBuilder &Results,
1568 const LangOptions &LangOpts) {
1569 if (!LangOpts.CPlusPlus11)
1570 return;
1571
1572 Builder.AddTypedTextChunk("static_assert");
1573 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1574 Builder.AddPlaceholderChunk("expression");
1575 Builder.AddChunk(CodeCompletionString::CK_Comma);
1576 Builder.AddPlaceholderChunk("message");
1577 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1578 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1579}
1580
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001581/// \brief Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001582static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001583 Scope *S,
1584 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001585 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001586 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001587 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001588
John McCall276321a2010-08-25 06:19:51 +00001589 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001590 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001591 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001592 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001593 if (Results.includeCodePatterns()) {
1594 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001595 Builder.AddTypedTextChunk("namespace");
1596 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1597 Builder.AddPlaceholderChunk("identifier");
1598 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1599 Builder.AddPlaceholderChunk("declarations");
1600 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1601 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1602 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001603 }
1604
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001605 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001606 Builder.AddTypedTextChunk("namespace");
1607 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1608 Builder.AddPlaceholderChunk("name");
1609 Builder.AddChunk(CodeCompletionString::CK_Equal);
1610 Builder.AddPlaceholderChunk("namespace");
1611 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001612
1613 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001614 Builder.AddTypedTextChunk("using");
1615 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1616 Builder.AddTextChunk("namespace");
1617 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1618 Builder.AddPlaceholderChunk("identifier");
1619 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001620
1621 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001622 Builder.AddTypedTextChunk("asm");
1623 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1624 Builder.AddPlaceholderChunk("string-literal");
1625 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1626 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001627
Douglas Gregorf4c33342010-05-28 00:22:41 +00001628 if (Results.includeCodePatterns()) {
1629 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001630 Builder.AddTypedTextChunk("template");
1631 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1632 Builder.AddPlaceholderChunk("declaration");
1633 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001634 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001635 }
Douglas Gregorf1934162010-01-13 21:24:21 +00001636
David Blaikiebbafb8a2012-03-11 07:00:24 +00001637 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001638 AddObjCTopLevelResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001639
Douglas Gregorf4c33342010-05-28 00:22:41 +00001640 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001641 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001642
John McCallfaf5fb42010-08-26 23:41:50 +00001643 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001644 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001645 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001646 Builder.AddTypedTextChunk("using");
1647 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1648 Builder.AddPlaceholderChunk("qualifier");
1649 Builder.AddTextChunk("::");
1650 Builder.AddPlaceholderChunk("name");
1651 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001652
Douglas Gregorf4c33342010-05-28 00:22:41 +00001653 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001654 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001655 Builder.AddTypedTextChunk("using");
1656 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1657 Builder.AddTextChunk("typename");
1658 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1659 Builder.AddPlaceholderChunk("qualifier");
1660 Builder.AddTextChunk("::");
1661 Builder.AddPlaceholderChunk("name");
1662 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001663 }
1664
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001665 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1666
John McCallfaf5fb42010-08-26 23:41:50 +00001667 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001668 AddTypedefResult(Results);
1669
Erik Verbruggen6524c052017-10-24 13:46:58 +00001670 bool IsNotInheritanceScope =
1671 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001672 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001673 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001674 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001675 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001676 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001677
1678 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001679 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001680 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001681 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001682 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001683
1684 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001685 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001686 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001687 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001688 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001689 }
1690 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001691 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001692
John McCallfaf5fb42010-08-26 23:41:50 +00001693 case Sema::PCC_Template:
1694 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001695 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001696 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001697 Builder.AddTypedTextChunk("template");
1698 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1699 Builder.AddPlaceholderChunk("parameters");
1700 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1701 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001702 }
1703
David Blaikiebbafb8a2012-03-11 07:00:24 +00001704 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1705 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001706 break;
1707
John McCallfaf5fb42010-08-26 23:41:50 +00001708 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001709 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1710 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1711 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001712 break;
1713
John McCallfaf5fb42010-08-26 23:41:50 +00001714 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001715 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1716 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1717 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001718 break;
1719
John McCallfaf5fb42010-08-26 23:41:50 +00001720 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001721 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001722 break;
1723
John McCallfaf5fb42010-08-26 23:41:50 +00001724 case Sema::PCC_RecoveryInFunction:
1725 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001726 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001727
David Blaikiebbafb8a2012-03-11 07:00:24 +00001728 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1729 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001730 Builder.AddTypedTextChunk("try");
1731 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1732 Builder.AddPlaceholderChunk("statements");
1733 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1734 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1735 Builder.AddTextChunk("catch");
1736 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1737 Builder.AddPlaceholderChunk("declaration");
1738 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1739 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1740 Builder.AddPlaceholderChunk("statements");
1741 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1742 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1743 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001744 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001745 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001746 AddObjCStatementResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001747
Douglas Gregorf64acca2010-05-25 21:41:55 +00001748 if (Results.includeCodePatterns()) {
1749 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001750 Builder.AddTypedTextChunk("if");
1751 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001752 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001753 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001754 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001755 Builder.AddPlaceholderChunk("expression");
1756 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1757 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1758 Builder.AddPlaceholderChunk("statements");
1759 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1760 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1761 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001762
Douglas Gregorf64acca2010-05-25 21:41:55 +00001763 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001764 Builder.AddTypedTextChunk("switch");
1765 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001766 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001767 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001768 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001769 Builder.AddPlaceholderChunk("expression");
1770 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1771 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1772 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1773 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1774 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001775 }
1776
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001777 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001778 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001779 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001780 Builder.AddTypedTextChunk("case");
1781 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1782 Builder.AddPlaceholderChunk("expression");
1783 Builder.AddChunk(CodeCompletionString::CK_Colon);
1784 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001785
1786 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001787 Builder.AddTypedTextChunk("default");
1788 Builder.AddChunk(CodeCompletionString::CK_Colon);
1789 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001790 }
1791
Douglas Gregorf64acca2010-05-25 21:41:55 +00001792 if (Results.includeCodePatterns()) {
1793 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001794 Builder.AddTypedTextChunk("while");
1795 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001796 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001797 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001798 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001799 Builder.AddPlaceholderChunk("expression");
1800 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1801 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1802 Builder.AddPlaceholderChunk("statements");
1803 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1804 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1805 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001806
1807 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001808 Builder.AddTypedTextChunk("do");
1809 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1810 Builder.AddPlaceholderChunk("statements");
1811 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1812 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1813 Builder.AddTextChunk("while");
1814 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1815 Builder.AddPlaceholderChunk("expression");
1816 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1817 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001818
Douglas Gregorf64acca2010-05-25 21:41:55 +00001819 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001820 Builder.AddTypedTextChunk("for");
1821 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001822 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001823 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001824 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001825 Builder.AddPlaceholderChunk("init-expression");
1826 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1827 Builder.AddPlaceholderChunk("condition");
1828 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1829 Builder.AddPlaceholderChunk("inc-expression");
1830 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1831 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1832 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1833 Builder.AddPlaceholderChunk("statements");
1834 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1835 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1836 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001837 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001838
1839 if (S->getContinueParent()) {
1840 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001841 Builder.AddTypedTextChunk("continue");
1842 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001843 }
1844
1845 if (S->getBreakParent()) {
1846 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001847 Builder.AddTypedTextChunk("break");
1848 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001849 }
1850
1851 // "return expression ;" or "return ;", depending on whether we
1852 // know the function is void or not.
1853 bool isVoid = false;
1854 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001855 isVoid = Function->getReturnType()->isVoidType();
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001856 else if (ObjCMethodDecl *Method
1857 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001858 isVoid = Method->getReturnType()->isVoidType();
Douglas Gregor9a28e842010-03-01 23:15:13 +00001859 else if (SemaRef.getCurBlock() &&
1860 !SemaRef.getCurBlock()->ReturnType.isNull())
1861 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001862 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001863 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001864 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1865 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001866 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001867 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001868
Douglas Gregorf4c33342010-05-28 00:22:41 +00001869 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001870 Builder.AddTypedTextChunk("goto");
1871 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1872 Builder.AddPlaceholderChunk("label");
1873 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001874
Douglas Gregorf4c33342010-05-28 00:22:41 +00001875 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001876 Builder.AddTypedTextChunk("using");
1877 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1878 Builder.AddTextChunk("namespace");
1879 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1880 Builder.AddPlaceholderChunk("identifier");
1881 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001882
1883 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001884 }
Galina Kistanovabe3ba9da2017-06-07 06:31:55 +00001885 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001886
1887 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001888 case Sema::PCC_ForInit:
1889 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001890 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001891 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00001892 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001893
Douglas Gregor5e35d592010-09-14 23:59:36 +00001894 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001895 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001896 CCC == Sema::PCC_ParenthesizedExpression) {
1897 // (__bridge <type>)<expression>
1898 Builder.AddTypedTextChunk("__bridge");
1899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1900 Builder.AddPlaceholderChunk("type");
1901 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1902 Builder.AddPlaceholderChunk("expression");
1903 Results.AddResult(Result(Builder.TakeString()));
1904
1905 // (__bridge_transfer <Objective-C type>)<expression>
1906 Builder.AddTypedTextChunk("__bridge_transfer");
1907 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1908 Builder.AddPlaceholderChunk("Objective-C type");
1909 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1910 Builder.AddPlaceholderChunk("expression");
1911 Results.AddResult(Result(Builder.TakeString()));
1912
1913 // (__bridge_retained <CF type>)<expression>
1914 Builder.AddTypedTextChunk("__bridge_retained");
1915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1916 Builder.AddPlaceholderChunk("CF type");
1917 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1918 Builder.AddPlaceholderChunk("expression");
1919 Results.AddResult(Result(Builder.TakeString()));
1920 }
1921 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00001922 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00001923
John McCallfaf5fb42010-08-26 23:41:50 +00001924 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001925 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001926 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001927 addThisCompletion(SemaRef, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001928
Douglas Gregore5c79d52011-10-18 21:20:17 +00001929 // true
1930 Builder.AddResultTypeChunk("bool");
1931 Builder.AddTypedTextChunk("true");
1932 Results.AddResult(Result(Builder.TakeString()));
1933
1934 // false
1935 Builder.AddResultTypeChunk("bool");
1936 Builder.AddTypedTextChunk("false");
1937 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001938
David Blaikiebbafb8a2012-03-11 07:00:24 +00001939 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001940 // dynamic_cast < type-id > ( expression )
1941 Builder.AddTypedTextChunk("dynamic_cast");
1942 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1943 Builder.AddPlaceholderChunk("type");
1944 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1945 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1946 Builder.AddPlaceholderChunk("expression");
1947 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1948 Results.AddResult(Result(Builder.TakeString()));
1949 }
Douglas Gregorf4c33342010-05-28 00:22:41 +00001950
1951 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001952 Builder.AddTypedTextChunk("static_cast");
1953 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1954 Builder.AddPlaceholderChunk("type");
1955 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1956 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1957 Builder.AddPlaceholderChunk("expression");
1958 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1959 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001960
Douglas Gregorf4c33342010-05-28 00:22:41 +00001961 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001962 Builder.AddTypedTextChunk("reinterpret_cast");
1963 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1964 Builder.AddPlaceholderChunk("type");
1965 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1966 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1967 Builder.AddPlaceholderChunk("expression");
1968 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1969 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001970
Douglas Gregorf4c33342010-05-28 00:22:41 +00001971 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001972 Builder.AddTypedTextChunk("const_cast");
1973 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1974 Builder.AddPlaceholderChunk("type");
1975 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1976 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1977 Builder.AddPlaceholderChunk("expression");
1978 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001980
David Blaikiebbafb8a2012-03-11 07:00:24 +00001981 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001982 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00001983 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001984 Builder.AddTypedTextChunk("typeid");
1985 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1986 Builder.AddPlaceholderChunk("expression-or-type");
1987 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1988 Results.AddResult(Result(Builder.TakeString()));
1989 }
1990
Douglas Gregorf4c33342010-05-28 00:22:41 +00001991 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001992 Builder.AddTypedTextChunk("new");
1993 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1994 Builder.AddPlaceholderChunk("type");
1995 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1996 Builder.AddPlaceholderChunk("expressions");
1997 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1998 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001999
Douglas Gregorf4c33342010-05-28 00:22:41 +00002000 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002001 Builder.AddTypedTextChunk("new");
2002 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2003 Builder.AddPlaceholderChunk("type");
2004 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2005 Builder.AddPlaceholderChunk("size");
2006 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2007 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2008 Builder.AddPlaceholderChunk("expressions");
2009 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2010 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002011
Douglas Gregorf4c33342010-05-28 00:22:41 +00002012 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002013 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002014 Builder.AddTypedTextChunk("delete");
2015 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2016 Builder.AddPlaceholderChunk("expression");
2017 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002018
Douglas Gregorf4c33342010-05-28 00:22:41 +00002019 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002020 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002021 Builder.AddTypedTextChunk("delete");
2022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2023 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2024 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2025 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2026 Builder.AddPlaceholderChunk("expression");
2027 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002028
David Blaikiebbafb8a2012-03-11 07:00:24 +00002029 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002030 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002031 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002032 Builder.AddTypedTextChunk("throw");
2033 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2034 Builder.AddPlaceholderChunk("expression");
2035 Results.AddResult(Result(Builder.TakeString()));
2036 }
Douglas Gregor4205fef2011-10-18 16:29:03 +00002037
Douglas Gregora2db7932010-05-26 22:00:08 +00002038 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002039
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002040 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002041 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002042 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002043 Builder.AddTypedTextChunk("nullptr");
2044 Results.AddResult(Result(Builder.TakeString()));
2045
2046 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002047 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002048 Builder.AddTypedTextChunk("alignof");
2049 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2050 Builder.AddPlaceholderChunk("type");
2051 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2052 Results.AddResult(Result(Builder.TakeString()));
2053
2054 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002055 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002056 Builder.AddTypedTextChunk("noexcept");
2057 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2058 Builder.AddPlaceholderChunk("expression");
2059 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2060 Results.AddResult(Result(Builder.TakeString()));
2061
2062 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002063 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002064 Builder.AddTypedTextChunk("sizeof...");
2065 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2066 Builder.AddPlaceholderChunk("parameter-pack");
2067 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2068 Results.AddResult(Result(Builder.TakeString()));
2069 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002070 }
2071
David Blaikiebbafb8a2012-03-11 07:00:24 +00002072 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002073 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002074 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2075 // The interface can be NULL.
2076 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002077 if (ID->getSuperClass()) {
2078 std::string SuperType;
2079 SuperType = ID->getSuperClass()->getNameAsString();
2080 if (Method->isInstanceMethod())
2081 SuperType += " *";
2082
2083 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2084 Builder.AddTypedTextChunk("super");
2085 Results.AddResult(Result(Builder.TakeString()));
2086 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002087 }
2088
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002089 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002090 }
2091
Jordan Rose58d54722012-06-30 21:33:57 +00002092 if (SemaRef.getLangOpts().C11) {
2093 // _Alignof
2094 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002095 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002096 Builder.AddTypedTextChunk("alignof");
2097 else
2098 Builder.AddTypedTextChunk("_Alignof");
2099 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2100 Builder.AddPlaceholderChunk("type");
2101 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2102 Results.AddResult(Result(Builder.TakeString()));
2103 }
2104
Douglas Gregorf4c33342010-05-28 00:22:41 +00002105 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002106 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002107 Builder.AddTypedTextChunk("sizeof");
2108 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2109 Builder.AddPlaceholderChunk("expression-or-type");
2110 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2111 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002112 break;
2113 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00002114
John McCallfaf5fb42010-08-26 23:41:50 +00002115 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002116 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002117 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002118 }
2119
David Blaikiebbafb8a2012-03-11 07:00:24 +00002120 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2121 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002122
David Blaikiebbafb8a2012-03-11 07:00:24 +00002123 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002124 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002125}
2126
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002127/// \brief If the given declaration has an associated type, add it as a result
2128/// type chunk.
2129static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002130 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002131 const NamedDecl *ND,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002132 QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002133 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002134 if (!ND)
2135 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002136
2137 // Skip constructors and conversion functions, which have their return types
2138 // built into their names.
2139 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2140 return;
2141
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002142 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002143 QualType T;
2144 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002145 T = Function->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002146 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
2147 if (!BaseType.isNull())
2148 T = Method->getSendResultType(BaseType);
2149 else
2150 T = Method->getReturnType();
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002151 } else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002152 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002153 T = clang::TypeName::getFullyQualifiedType(T, Context);
2154 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002155 /* Do nothing: ignore unresolved using declarations*/
Douglas Gregorc3425b12015-07-07 06:20:19 +00002156 } else if (const ObjCIvarDecl *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
2157 if (!BaseType.isNull())
2158 T = Ivar->getUsageType(BaseType);
2159 else
2160 T = Ivar->getType();
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002161 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002162 T = Value->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002163 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
2164 if (!BaseType.isNull())
2165 T = Property->getUsageType(BaseType);
2166 else
2167 T = Property->getType();
2168 }
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002169
2170 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2171 return;
2172
Douglas Gregor75acd922011-09-27 23:30:47 +00002173 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002174 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002175}
2176
Richard Smith20e883e2015-04-29 23:20:19 +00002177static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002178 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002179 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002180 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2181 if (Sentinel->getSentinel() == 0) {
Richard Smith20e883e2015-04-29 23:20:19 +00002182 if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002183 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002184 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002185 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002186 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002187 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002188 }
2189}
2190
Douglas Gregor86b42682015-06-19 18:27:52 +00002191static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
2192 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002193 std::string Result;
2194 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002195 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002196 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002197 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002198 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002199 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002200 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002201 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002202 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002203 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002204 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002205 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002206 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2207 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2208 switch (*nullability) {
2209 case NullabilityKind::NonNull:
2210 Result += "nonnull ";
2211 break;
2212
2213 case NullabilityKind::Nullable:
2214 Result += "nullable ";
2215 break;
2216
2217 case NullabilityKind::Unspecified:
2218 Result += "null_unspecified ";
2219 break;
2220 }
2221 }
2222 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002223 return Result;
2224}
2225
Alex Lorenza1951202016-10-18 10:35:27 +00002226/// \brief Tries to find the most appropriate type location for an Objective-C
2227/// block placeholder.
2228///
2229/// This function ignores things like typedefs and qualifiers in order to
2230/// present the most relevant and accurate block placeholders in code completion
2231/// results.
2232static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2233 FunctionTypeLoc &Block,
2234 FunctionProtoTypeLoc &BlockProto,
2235 bool SuppressBlock = false) {
2236 if (!TSInfo)
2237 return;
2238 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2239 while (true) {
2240 // Look through typedefs.
2241 if (!SuppressBlock) {
2242 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2243 if (TypeSourceInfo *InnerTSInfo =
2244 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2245 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2246 continue;
2247 }
2248 }
2249
2250 // Look through qualified types
2251 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2252 TL = QualifiedTL.getUnqualifiedLoc();
2253 continue;
2254 }
2255
2256 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2257 TL = AttrTL.getModifiedLoc();
2258 continue;
2259 }
2260 }
2261
2262 // Try to get the function prototype behind the block pointer type,
2263 // then we're done.
2264 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2265 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2266 Block = TL.getAs<FunctionTypeLoc>();
2267 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2268 }
2269 break;
2270 }
2271}
2272
Alex Lorenz920ae142016-10-18 10:38:58 +00002273static std::string
2274formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2275 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002276 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002277 bool SuppressBlock = false,
2278 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2279
Richard Smith20e883e2015-04-29 23:20:19 +00002280static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002281 const ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002282 bool SuppressName = false,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002283 bool SuppressBlock = false,
2284 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002285 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2286 if (Param->getType()->isDependentType() ||
2287 !Param->getType()->isBlockPointerType()) {
2288 // The argument for a dependent or non-block parameter is a placeholder
2289 // containing that parameter's type.
2290 std::string Result;
2291
Douglas Gregor981a0c42010-08-29 19:47:46 +00002292 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002293 Result = Param->getIdentifier()->getName();
2294
Douglas Gregor86b42682015-06-19 18:27:52 +00002295 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002296 if (ObjCSubsts)
2297 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2298 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002299 if (ObjCMethodParam) {
Douglas Gregor86b42682015-06-19 18:27:52 +00002300 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
2301 Type);
2302 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002303 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002304 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002305 } else {
2306 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002307 }
2308 return Result;
2309 }
Alex Lorenza1951202016-10-18 10:35:27 +00002310
Douglas Gregore90dd002010-08-24 16:15:59 +00002311 // The argument for a block pointer parameter is a block literal with
2312 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002313 FunctionTypeLoc Block;
2314 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002315 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2316 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002317 // Try to retrieve the block type information from the property if this is a
2318 // parameter in a setter.
2319 if (!Block && ObjCMethodParam &&
2320 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2321 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2322 ->findPropertyDecl(/*CheckOverrides=*/false))
2323 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2324 SuppressBlock);
2325 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002326
2327 if (!Block) {
2328 // We were unable to find a FunctionProtoTypeLoc with parameter names
2329 // for the block; just use the parameter type as a placeholder.
2330 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002331 if (!ObjCMethodParam && Param->getIdentifier())
2332 Result = Param->getIdentifier()->getName();
2333
Douglas Gregor86b42682015-06-19 18:27:52 +00002334 QualType Type = Param->getType().getUnqualifiedType();
Douglas Gregore90dd002010-08-24 16:15:59 +00002335
2336 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002337 Result = Type.getAsString(Policy);
2338 std::string Quals =
2339 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2340 if (!Quals.empty())
2341 Result = "(" + Quals + " " + Result + ")";
2342 if (Result.back() != ')')
2343 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002344 if (Param->getIdentifier())
2345 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002346 } else {
2347 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002348 }
2349
2350 return Result;
2351 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002352
Douglas Gregore90dd002010-08-24 16:15:59 +00002353 // We have the function prototype behind the block pointer type, as it was
2354 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002355 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2356 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002357 ObjCSubsts);
2358}
2359
2360/// \brief Returns a placeholder string that corresponds to an Objective-C block
2361/// declaration.
2362///
2363/// \param BlockDecl A declaration with an Objective-C block type.
2364///
2365/// \param Block The most relevant type location for that block type.
2366///
2367/// \param SuppressBlockName Determines wether or not the name of the block
2368/// declaration is included in the resulting string.
2369static std::string
2370formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2371 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002372 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002373 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002374 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002375 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002376 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002377 ResultType =
2378 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2379 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002380 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002381 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002382
2383 // Format the parameter list.
2384 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002385 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002386 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002387 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002388 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002389 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002390 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002391 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002392 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002393 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002394 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002395 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002396 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002397 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002398
David Blaikie6adc78e2013-02-18 22:06:02 +00002399 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002400 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002401 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002402 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002403 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002404
Douglas Gregord793e7c2011-10-18 04:23:19 +00002405 if (SuppressBlock) {
2406 // Format as a parameter.
2407 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002408 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002409 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002410 Result += ")";
2411 Result += Params;
2412 } else {
2413 // Format as a block literal argument.
2414 Result = '^' + Result;
2415 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002416
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002417 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002418 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002419 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002420
Douglas Gregore90dd002010-08-24 16:15:59 +00002421 return Result;
2422}
2423
Erik Verbruggen11338c52017-07-19 10:45:40 +00002424static std::string GetDefaultValueString(const ParmVarDecl *Param,
2425 const SourceManager &SM,
2426 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002427 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002428 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2429 bool Invalid = CharSrcRange.isInvalid();
2430 if (Invalid)
2431 return "";
2432 StringRef srcText = Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
2433 if (Invalid)
2434 return "";
2435
2436 if (srcText.empty() || srcText == "=") {
2437 // Lexer can't determine the value.
2438 // This happens if the code is incorrect (for example class is forward declared).
2439 return "";
2440 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002441 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002442 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2443 // this value always has (or always does not have) '=' in front of it
2444 if (DefValue.at(0) != '=') {
2445 // If we don't have '=' in front of value.
2446 // Lexer returns built-in types values without '=' and user-defined types values with it.
2447 return " = " + DefValue;
2448 }
2449 return " " + DefValue;
2450}
2451
Douglas Gregor3545ff42009-09-21 16:56:56 +00002452/// \brief Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002453static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002454 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002455 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002456 CodeCompletionBuilder &Result,
2457 unsigned Start = 0,
2458 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002459 bool FirstParameter = true;
Douglas Gregor9eb77012009-11-07 00:00:49 +00002460
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002461 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002462 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002463
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002464 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002465 // When we see an optional default argument, put that argument and
2466 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002467 CodeCompletionBuilder Opt(Result.getAllocator(),
2468 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002469 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002470 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002471 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002472 Result.AddOptionalChunk(Opt.TakeString());
2473 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002474 }
2475
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002476 if (FirstParameter)
2477 FirstParameter = false;
2478 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002479 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002480
2481 InOptional = false;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002482
2483 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002484 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002485 if (Param->hasDefaultArg())
2486 PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002487
Douglas Gregor400f5972010-08-31 05:13:43 +00002488 if (Function->isVariadic() && P == N - 1)
2489 PlaceholderStr += ", ...";
2490
Douglas Gregor3545ff42009-09-21 16:56:56 +00002491 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002492 Result.AddPlaceholderChunk(
2493 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002494 }
Douglas Gregorba449032009-09-22 21:42:17 +00002495
2496 if (const FunctionProtoType *Proto
2497 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002498 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002499 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002500 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002501
Richard Smith20e883e2015-04-29 23:20:19 +00002502 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002503 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002504}
2505
2506/// \brief Add template parameter chunks to the given code completion string.
2507static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002508 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002509 const TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002510 CodeCompletionBuilder &Result,
2511 unsigned MaxParameters = 0,
2512 unsigned Start = 0,
2513 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002514 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002515
2516 // Prefer to take the template parameter names from the first declaration of
2517 // the template.
2518 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2519
Douglas Gregor3545ff42009-09-21 16:56:56 +00002520 TemplateParameterList *Params = Template->getTemplateParameters();
2521 TemplateParameterList::iterator PEnd = Params->end();
2522 if (MaxParameters)
2523 PEnd = Params->begin() + MaxParameters;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002524 for (TemplateParameterList::iterator P = Params->begin() + Start;
2525 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002526 bool HasDefaultArg = false;
2527 std::string PlaceholderStr;
2528 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2529 if (TTP->wasDeclaredWithTypename())
2530 PlaceholderStr = "typename";
2531 else
2532 PlaceholderStr = "class";
2533
2534 if (TTP->getIdentifier()) {
2535 PlaceholderStr += ' ';
2536 PlaceholderStr += TTP->getIdentifier()->getName();
2537 }
2538
2539 HasDefaultArg = TTP->hasDefaultArgument();
2540 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002541 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002542 if (NTTP->getIdentifier())
2543 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002544 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002545 HasDefaultArg = NTTP->hasDefaultArgument();
2546 } else {
2547 assert(isa<TemplateTemplateParmDecl>(*P));
2548 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2549
2550 // Since putting the template argument list into the placeholder would
2551 // be very, very long, we just use an abbreviation.
2552 PlaceholderStr = "template<...> class";
2553 if (TTP->getIdentifier()) {
2554 PlaceholderStr += ' ';
2555 PlaceholderStr += TTP->getIdentifier()->getName();
2556 }
2557
2558 HasDefaultArg = TTP->hasDefaultArgument();
2559 }
2560
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002561 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002562 // When we see an optional default argument, put that argument and
2563 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002564 CodeCompletionBuilder Opt(Result.getAllocator(),
2565 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002566 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002567 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002568 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002569 P - Params->begin(), true);
2570 Result.AddOptionalChunk(Opt.TakeString());
2571 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002572 }
2573
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002574 InDefaultArg = false;
2575
Douglas Gregor3545ff42009-09-21 16:56:56 +00002576 if (FirstParameter)
2577 FirstParameter = false;
2578 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002579 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002580
2581 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002582 Result.AddPlaceholderChunk(
2583 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002584 }
2585}
2586
Douglas Gregorf2510672009-09-21 19:57:38 +00002587/// \brief Add a qualifier to the given code-completion string, if the
2588/// provided nested-name-specifier is non-NULL.
Douglas Gregor0f622362009-12-11 18:44:16 +00002589static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002590AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregor0f622362009-12-11 18:44:16 +00002591 NestedNameSpecifier *Qualifier,
2592 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002593 ASTContext &Context,
2594 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002595 if (!Qualifier)
2596 return;
2597
2598 std::string PrintedNNS;
2599 {
2600 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002601 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002602 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002603 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002604 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002605 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002606 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002607}
2608
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002609static void
2610AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002611 const FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002612 const FunctionProtoType *Proto
2613 = Function->getType()->getAs<FunctionProtoType>();
2614 if (!Proto || !Proto->getTypeQuals())
2615 return;
2616
Douglas Gregor304f9b02011-02-01 21:15:40 +00002617 // FIXME: Add ref-qualifier!
2618
2619 // Handle single qualifiers without copying
2620 if (Proto->getTypeQuals() == Qualifiers::Const) {
2621 Result.AddInformativeChunk(" const");
2622 return;
2623 }
2624
2625 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2626 Result.AddInformativeChunk(" volatile");
2627 return;
2628 }
2629
2630 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2631 Result.AddInformativeChunk(" restrict");
2632 return;
2633 }
2634
2635 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002636 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002637 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002638 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002639 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002640 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002641 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002642 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002643 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002644}
2645
Douglas Gregor0212fd72010-09-21 16:06:22 +00002646/// \brief Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002647static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002648 const NamedDecl *ND,
2649 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002650 DeclarationName Name = ND->getDeclName();
2651 if (!Name)
2652 return;
2653
2654 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002655 case DeclarationName::CXXOperatorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002656 const char *OperatorName = nullptr;
Douglas Gregor304f9b02011-02-01 21:15:40 +00002657 switch (Name.getCXXOverloadedOperator()) {
2658 case OO_None:
2659 case OO_Conditional:
2660 case NUM_OVERLOADED_OPERATORS:
2661 OperatorName = "operator";
2662 break;
2663
2664#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2665 case OO_##Name: OperatorName = "operator" Spelling; break;
2666#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2667#include "clang/Basic/OperatorKinds.def"
2668
2669 case OO_New: OperatorName = "operator new"; break;
2670 case OO_Delete: OperatorName = "operator delete"; break;
2671 case OO_Array_New: OperatorName = "operator new[]"; break;
2672 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2673 case OO_Call: OperatorName = "operator()"; break;
2674 case OO_Subscript: OperatorName = "operator[]"; break;
2675 }
2676 Result.AddTypedTextChunk(OperatorName);
2677 break;
2678 }
2679
Douglas Gregor0212fd72010-09-21 16:06:22 +00002680 case DeclarationName::Identifier:
2681 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002682 case DeclarationName::CXXDestructorName:
2683 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002684 Result.AddTypedTextChunk(
2685 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002686 break;
2687
Richard Smith35845152017-02-07 01:37:30 +00002688 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002689 case DeclarationName::CXXUsingDirective:
2690 case DeclarationName::ObjCZeroArgSelector:
2691 case DeclarationName::ObjCOneArgSelector:
2692 case DeclarationName::ObjCMultiArgSelector:
2693 break;
2694
2695 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002696 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002697 QualType Ty = Name.getCXXNameType();
2698 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2699 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2700 else if (const InjectedClassNameType *InjectedTy
2701 = Ty->getAs<InjectedClassNameType>())
2702 Record = InjectedTy->getDecl();
2703 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002704 Result.AddTypedTextChunk(
2705 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002706 break;
2707 }
2708
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002709 Result.AddTypedTextChunk(
2710 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002711 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002712 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002713 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002714 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002715 }
2716 break;
2717 }
2718 }
2719}
2720
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002721CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002722 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002723 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002724 CodeCompletionTUInfo &CCTUInfo,
2725 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002726 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2727 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002728}
2729
Douglas Gregor3545ff42009-09-21 16:56:56 +00002730/// \brief If possible, create a new code completion string for the given
2731/// result.
2732///
2733/// \returns Either a new, heap-allocated code completion string describing
2734/// how to use this result, or NULL to indicate that the string or name of the
2735/// result is all that is needed.
2736CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002737CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2738 Preprocessor &PP,
Douglas Gregorc3425b12015-07-07 06:20:19 +00002739 const CodeCompletionContext &CCContext,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002740 CodeCompletionAllocator &Allocator,
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002741 CodeCompletionTUInfo &CCTUInfo,
2742 bool IncludeBriefComments) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002743 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor9eb77012009-11-07 00:00:49 +00002744
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002745 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002746 if (Kind == RK_Pattern) {
2747 Pattern->Priority = Priority;
2748 Pattern->Availability = Availability;
Douglas Gregor78254c82012-03-27 23:34:16 +00002749
2750 if (Declaration) {
2751 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002752 Pattern->ParentName = Result.getParentName();
Fariborz Jahanian1fcf4922013-03-22 17:55:27 +00002753 // Provide code completion comment for self.GetterName where
2754 // GetterName is the getter method for a property with name
2755 // different from the property name (declared via a property
2756 // getter attribute.
2757 const NamedDecl *ND = Declaration;
2758 if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND))
2759 if (M->isPropertyAccessor())
2760 if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl())
2761 if (PDecl->getGetterName() == M->getSelector() &&
Fariborz Jahanianbe8bc672013-03-23 01:10:45 +00002762 PDecl->getIdentifier() != M->getIdentifier()) {
2763 if (const RawComment *RC =
2764 Ctx.getRawCommentForAnyRedecl(M)) {
Fariborz Jahanian1fcf4922013-03-22 17:55:27 +00002765 Result.addBriefComment(RC->getBriefText(Ctx));
2766 Pattern->BriefComment = Result.getBriefComment();
2767 }
Fariborz Jahanianbe8bc672013-03-23 01:10:45 +00002768 else if (const RawComment *RC =
2769 Ctx.getRawCommentForAnyRedecl(PDecl)) {
2770 Result.addBriefComment(RC->getBriefText(Ctx));
2771 Pattern->BriefComment = Result.getBriefComment();
2772 }
2773 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002774 }
2775
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002776 return Pattern;
2777 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002778
Douglas Gregorf09935f2009-12-01 05:55:20 +00002779 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002780 Result.AddTypedTextChunk(Keyword);
2781 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002782 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002783
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002784 if (Kind == RK_Macro) {
Richard Smith20e883e2015-04-29 23:20:19 +00002785 const MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002786 Result.AddTypedTextChunk(
2787 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002788
Ben Langmuirc28ce3a2014-09-30 20:00:18 +00002789 if (!MI || !MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002790 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002791
2792 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002793 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Faisal Valiac506d72017-07-17 17:18:43 +00002794 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002795
2796 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2797 if (MI->isC99Varargs()) {
2798 --AEnd;
2799
2800 if (A == AEnd) {
2801 Result.AddPlaceholderChunk("...");
2802 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002803 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002804
Faisal Valiac506d72017-07-17 17:18:43 +00002805 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2806 if (A != MI->param_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002807 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002808
2809 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002810 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002811 if (MI->isC99Varargs())
2812 Arg += ", ...";
2813 else
2814 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002815 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002816 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002817 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002818
2819 // Non-variadic macros are simple.
2820 Result.AddPlaceholderChunk(
2821 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002822 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002823 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002824 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002825 }
2826
Douglas Gregorf64acca2010-05-25 21:41:55 +00002827 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002828 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002829 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002830
2831 if (IncludeBriefComments) {
2832 // Add documentation comment, if it exists.
Dmitri Gribenkoa43ec182012-08-11 00:51:43 +00002833 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002834 Result.addBriefComment(RC->getBriefText(Ctx));
Fariborz Jahanian15a0b552013-02-28 17:47:14 +00002835 }
2836 else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
2837 if (OMD->isPropertyAccessor())
2838 if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
2839 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
2840 Result.addBriefComment(RC->getBriefText(Ctx));
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002841 }
2842
Douglas Gregor9eb77012009-11-07 00:00:49 +00002843 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002844 Result.AddTypedTextChunk(
2845 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002846 Result.AddTextChunk("::");
2847 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002848 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002849
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002850 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2851 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002852
Douglas Gregorc3425b12015-07-07 06:20:19 +00002853 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002854
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002855 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002856 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002857 Ctx, Policy);
2858 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002859 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002860 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002861 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002862 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002863 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002864 }
2865
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002866 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002867 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002868 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002869 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002870 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002871
Douglas Gregor3545ff42009-09-21 16:56:56 +00002872 // Figure out which template parameters are deduced (or have default
2873 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002874 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002875 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002876 unsigned LastDeducibleArgument;
2877 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2878 --LastDeducibleArgument) {
2879 if (!Deduced[LastDeducibleArgument - 1]) {
2880 // C++0x: Figure out if the template argument has a default. If so,
2881 // the user doesn't need to type this argument.
2882 // FIXME: We need to abstract template parameters better!
2883 bool HasDefaultArg = false;
2884 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002885 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002886 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2887 HasDefaultArg = TTP->hasDefaultArgument();
2888 else if (NonTypeTemplateParmDecl *NTTP
2889 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2890 HasDefaultArg = NTTP->hasDefaultArgument();
2891 else {
2892 assert(isa<TemplateTemplateParmDecl>(Param));
2893 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002894 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002895 }
2896
2897 if (!HasDefaultArg)
2898 break;
2899 }
2900 }
2901
2902 if (LastDeducibleArgument) {
2903 // Some of the function template arguments cannot be deduced from a
2904 // function call, so we introduce an explicit template argument list
2905 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002906 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002907 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002908 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002909 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002910 }
2911
2912 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002913 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00002914 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002915 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002916 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002917 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002918 }
2919
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002920 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002921 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002922 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002923 Result.AddTypedTextChunk(
2924 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002925 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002926 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002927 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002928 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002929 }
2930
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002931 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002932 Selector Sel = Method->getSelector();
2933 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002934 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002935 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002936 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002937 }
2938
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002939 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002940 SelName += ':';
2941 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002942 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002943 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002944 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002945
2946 // If there is only one parameter, and we're past it, add an empty
2947 // typed-text chunk since there is nothing to type.
2948 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002949 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002950 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002951 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002952 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2953 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002954 P != PEnd; (void)++P, ++Idx) {
2955 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002956 std::string Keyword;
2957 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002958 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002959 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002960 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002961 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002962 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002963 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002964 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002965 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002966 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002967
2968 // If we're before the starting parameter, skip the placeholder.
2969 if (Idx < StartParameter)
2970 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002971
2972 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00002973 QualType ParamType = (*P)->getType();
2974 Optional<ArrayRef<QualType>> ObjCSubsts;
2975 if (!CCContext.getBaseType().isNull())
2976 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
2977
2978 if (ParamType->isBlockPointerType() && !DeclaringEntity)
2979 Arg = FormatFunctionParameter(Policy, *P, true,
2980 /*SuppressBlock=*/false,
2981 ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00002982 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002983 if (ObjCSubsts)
2984 ParamType = ParamType.substObjCTypeArgs(Ctx, *ObjCSubsts,
2985 ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00002986 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00002987 ParamType);
2988 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002989 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002990 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002991 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002992 }
2993
Douglas Gregor400f5972010-08-31 05:13:43 +00002994 if (Method->isVariadic() && (P + 1) == PEnd)
2995 Arg += ", ...";
2996
Douglas Gregor95887f92010-07-08 23:20:03 +00002997 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002998 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00002999 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003000 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003001 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003002 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003003 }
3004
Douglas Gregor04c5f972009-12-23 00:21:46 +00003005 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003006 if (Method->param_size() == 0) {
3007 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003008 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003009 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003010 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003011 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003012 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003013 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00003014
Richard Smith20e883e2015-04-29 23:20:19 +00003015 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003016 }
3017
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003018 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003019 }
3020
Douglas Gregorf09935f2009-12-01 05:55:20 +00003021 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00003022 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003023 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003024
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003025 Result.AddTypedTextChunk(
3026 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003027 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003028}
3029
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003030/// \brief Add function overload parameter chunks to the given code completion
3031/// string.
3032static void AddOverloadParameterChunks(ASTContext &Context,
3033 const PrintingPolicy &Policy,
3034 const FunctionDecl *Function,
3035 const FunctionProtoType *Prototype,
3036 CodeCompletionBuilder &Result,
3037 unsigned CurrentArg,
3038 unsigned Start = 0,
3039 bool InOptional = false) {
3040 bool FirstParameter = true;
3041 unsigned NumParams = Function ? Function->getNumParams()
3042 : Prototype->getNumParams();
3043
3044 for (unsigned P = Start; P != NumParams; ++P) {
3045 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3046 // When we see an optional default argument, put that argument and
3047 // the remaining default arguments into a new, optional string.
3048 CodeCompletionBuilder Opt(Result.getAllocator(),
3049 Result.getCodeCompletionTUInfo());
3050 if (!FirstParameter)
3051 Opt.AddChunk(CodeCompletionString::CK_Comma);
3052 // Optional sections are nested.
3053 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3054 CurrentArg, P, /*InOptional=*/true);
3055 Result.AddOptionalChunk(Opt.TakeString());
3056 return;
3057 }
3058
3059 if (FirstParameter)
3060 FirstParameter = false;
3061 else
3062 Result.AddChunk(CodeCompletionString::CK_Comma);
3063
3064 InOptional = false;
3065
3066 // Format the placeholder string.
3067 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003068 if (Function) {
3069 const ParmVarDecl *Param = Function->getParamDecl(P);
3070 Placeholder = FormatFunctionParameter(Policy, Param);
3071 if (Param->hasDefaultArg())
3072 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), Context.getLangOpts());
3073 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003074 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003075 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003076
3077 if (P == CurrentArg)
3078 Result.AddCurrentParameterChunk(
3079 Result.getAllocator().CopyString(Placeholder));
3080 else
3081 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3082 }
3083
3084 if (Prototype && Prototype->isVariadic()) {
3085 CodeCompletionBuilder Opt(Result.getAllocator(),
3086 Result.getCodeCompletionTUInfo());
3087 if (!FirstParameter)
3088 Opt.AddChunk(CodeCompletionString::CK_Comma);
3089
3090 if (CurrentArg < NumParams)
3091 Opt.AddPlaceholderChunk("...");
3092 else
3093 Opt.AddCurrentParameterChunk("...");
3094
3095 Result.AddOptionalChunk(Opt.TakeString());
3096 }
3097}
3098
Douglas Gregorf0f51982009-09-23 00:34:09 +00003099CodeCompletionString *
3100CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003101 unsigned CurrentArg, Sema &S,
3102 CodeCompletionAllocator &Allocator,
3103 CodeCompletionTUInfo &CCTUInfo,
3104 bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003105 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003106
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003107 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003108 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003109 FunctionDecl *FDecl = getFunction();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003110 const FunctionProtoType *Proto
Douglas Gregorf0f51982009-09-23 00:34:09 +00003111 = dyn_cast<FunctionProtoType>(getFunctionType());
3112 if (!FDecl && !Proto) {
3113 // Function without a prototype. Just give the return type and a
3114 // highlighted ellipsis.
3115 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003116 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
3117 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003118 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3119 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3120 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003121 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003122 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003123
3124 if (FDecl) {
3125 if (IncludeBriefComments && CurrentArg < FDecl->getNumParams())
3126 if (auto RC = S.getASTContext().getRawCommentForAnyRedecl(
3127 FDecl->getParamDecl(CurrentArg)))
3128 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Douglas Gregorc3425b12015-07-07 06:20:19 +00003129 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003130 Result.AddTextChunk(
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003131 Result.getAllocator().CopyString(FDecl->getNameAsString()));
3132 } else {
3133 Result.AddResultTypeChunk(
3134 Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003135 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003136 }
Alp Toker314cc812014-01-25 16:55:45 +00003137
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003138 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003139 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3140 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003141 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003142
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003143 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003144}
3145
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003146unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003147 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003148 bool PreferredTypeIsPointer) {
3149 unsigned Priority = CCP_Macro;
3150
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003151 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
3152 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
3153 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003154 Priority = CCP_Constant;
3155 if (PreferredTypeIsPointer)
3156 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003157 }
3158 // Treat "YES", "NO", "true", and "false" as constants.
3159 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3160 MacroName.equals("true") || MacroName.equals("false"))
3161 Priority = CCP_Constant;
3162 // Treat "bool" as a type.
3163 else if (MacroName.equals("bool"))
3164 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
3165
Douglas Gregor6e240332010-08-16 16:18:59 +00003166
3167 return Priority;
3168}
3169
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003170CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003171 if (!D)
3172 return CXCursor_UnexposedDecl;
3173
3174 switch (D->getKind()) {
3175 case Decl::Enum: return CXCursor_EnumDecl;
3176 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
3177 case Decl::Field: return CXCursor_FieldDecl;
3178 case Decl::Function:
3179 return CXCursor_FunctionDecl;
3180 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
3181 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003182 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003183
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003184 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003185 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
3186 case Decl::ObjCMethod:
3187 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3188 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
3189 case Decl::CXXMethod: return CXCursor_CXXMethod;
3190 case Decl::CXXConstructor: return CXCursor_Constructor;
3191 case Decl::CXXDestructor: return CXCursor_Destructor;
3192 case Decl::CXXConversion: return CXCursor_ConversionFunction;
3193 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00003194 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003195 case Decl::ParmVar: return CXCursor_ParmDecl;
3196 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00003197 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Sergey Kalinichev8f3b1872015-11-15 13:48:32 +00003198 case Decl::TypeAliasTemplate: return CXCursor_TypeAliasTemplateDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003199 case Decl::Var: return CXCursor_VarDecl;
3200 case Decl::Namespace: return CXCursor_Namespace;
3201 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
3202 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
3203 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
3204 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
3205 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
3206 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00003207 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003208 case Decl::ClassTemplatePartialSpecialization:
3209 return CXCursor_ClassTemplatePartialSpecialization;
3210 case Decl::UsingDirective: return CXCursor_UsingDirective;
Olivier Goffart81978012016-06-09 16:15:55 +00003211 case Decl::StaticAssert: return CXCursor_StaticAssert;
Olivier Goffartd211c642016-11-04 06:29:27 +00003212 case Decl::Friend: return CXCursor_FriendDecl;
Douglas Gregor3e653b32012-04-30 23:41:16 +00003213 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003214
3215 case Decl::Using:
3216 case Decl::UnresolvedUsingValue:
3217 case Decl::UnresolvedUsingTypename:
3218 return CXCursor_UsingDeclaration;
3219
Douglas Gregor4cd65962011-06-03 23:08:58 +00003220 case Decl::ObjCPropertyImpl:
3221 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3222 case ObjCPropertyImplDecl::Dynamic:
3223 return CXCursor_ObjCDynamicDecl;
3224
3225 case ObjCPropertyImplDecl::Synthesize:
3226 return CXCursor_ObjCSynthesizeDecl;
3227 }
Argyrios Kyrtzidis50e5b1d2012-10-05 00:22:24 +00003228
3229 case Decl::Import:
3230 return CXCursor_ModuleImportDecl;
Douglas Gregor85f3f952015-07-07 03:57:15 +00003231
3232 case Decl::ObjCTypeParam: return CXCursor_TemplateTypeParameter;
3233
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003234 default:
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003235 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003236 switch (TD->getTagKind()) {
Joao Matosdc86f942012-08-31 18:45:21 +00003237 case TTK_Interface: // fall through
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003238 case TTK_Struct: return CXCursor_StructDecl;
3239 case TTK_Class: return CXCursor_ClassDecl;
3240 case TTK_Union: return CXCursor_UnionDecl;
3241 case TTK_Enum: return CXCursor_EnumDecl;
3242 }
3243 }
3244 }
3245
3246 return CXCursor_UnexposedDecl;
3247}
3248
Douglas Gregor55b037b2010-07-08 20:55:51 +00003249static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor8cb17462012-10-09 16:01:50 +00003250 bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003251 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003252 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00003253
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003254 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003255
Douglas Gregor9eb77012009-11-07 00:00:49 +00003256 for (Preprocessor::macro_iterator M = PP.macro_begin(),
3257 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003258 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003259 auto MD = PP.getMacroDefinition(M->first);
3260 if (IncludeUndefined || MD) {
3261 if (MacroInfo *MI = MD.getMacroInfo())
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003262 if (MI->isUsedForHeaderGuard())
3263 continue;
3264
Douglas Gregor8cb17462012-10-09 16:01:50 +00003265 Results.AddResult(Result(M->first,
Douglas Gregor6e240332010-08-16 16:18:59 +00003266 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00003267 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00003268 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003269 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003270 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003271
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003272 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003273
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003274}
3275
Douglas Gregorce0e8562010-08-23 21:54:33 +00003276static void AddPrettyFunctionResults(const LangOptions &LangOpts,
3277 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003278 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003279
3280 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00003281
Douglas Gregorce0e8562010-08-23 21:54:33 +00003282 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3283 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003284 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003285 Results.AddResult(Result("__func__", CCP_Constant));
3286 Results.ExitScope();
3287}
3288
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003289static void HandleCodeCompleteResults(Sema *S,
3290 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003291 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003292 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003293 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003294 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003295 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003296}
3297
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003298static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
3299 Sema::ParserCompletionContext PCC) {
3300 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003301 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003302 return CodeCompletionContext::CCC_TopLevel;
3303
John McCallfaf5fb42010-08-26 23:41:50 +00003304 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003305 return CodeCompletionContext::CCC_ClassStructUnion;
3306
John McCallfaf5fb42010-08-26 23:41:50 +00003307 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003308 return CodeCompletionContext::CCC_ObjCInterface;
3309
John McCallfaf5fb42010-08-26 23:41:50 +00003310 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003311 return CodeCompletionContext::CCC_ObjCImplementation;
3312
John McCallfaf5fb42010-08-26 23:41:50 +00003313 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003314 return CodeCompletionContext::CCC_ObjCIvarList;
3315
John McCallfaf5fb42010-08-26 23:41:50 +00003316 case Sema::PCC_Template:
3317 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003318 if (S.CurContext->isFileContext())
3319 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003320 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003321 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003322 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00003323
John McCallfaf5fb42010-08-26 23:41:50 +00003324 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003325 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003326
John McCallfaf5fb42010-08-26 23:41:50 +00003327 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003328 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3329 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003330 return CodeCompletionContext::CCC_ParenthesizedExpression;
3331 else
3332 return CodeCompletionContext::CCC_Expression;
3333
3334 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003335 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003336 return CodeCompletionContext::CCC_Expression;
3337
John McCallfaf5fb42010-08-26 23:41:50 +00003338 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003339 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003340
John McCallfaf5fb42010-08-26 23:41:50 +00003341 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003342 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003343
3344 case Sema::PCC_ParenthesizedExpression:
3345 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00003346
3347 case Sema::PCC_LocalDeclarationSpecifiers:
3348 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003349 }
David Blaikie8a40f702012-01-17 06:56:22 +00003350
3351 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003352}
3353
Douglas Gregorac322ec2010-08-27 21:18:54 +00003354/// \brief If we're in a C++ virtual member function, add completion results
3355/// that invoke the functions we override, since it's common to invoke the
3356/// overridden function as well as adding new functionality.
3357///
3358/// \param S The semantic analysis object for which we are generating results.
3359///
3360/// \param InContext This context in which the nested-name-specifier preceding
3361/// the code-completion point
3362static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3363 ResultBuilder &Results) {
3364 // Look through blocks.
3365 DeclContext *CurContext = S.CurContext;
3366 while (isa<BlockDecl>(CurContext))
3367 CurContext = CurContext->getParent();
3368
3369
3370 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3371 if (!Method || !Method->isVirtual())
3372 return;
3373
3374 // We need to have names for all of the parameters, if we're going to
3375 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003376 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003377 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003378 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003379
Douglas Gregor75acd922011-09-27 23:30:47 +00003380 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003381 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003382 CodeCompletionBuilder Builder(Results.getAllocator(),
3383 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003384 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3385 continue;
3386
3387 // If we need a nested-name-specifier, add one now.
3388 if (!InContext) {
3389 NestedNameSpecifier *NNS
3390 = getRequiredQualification(S.Context, CurContext,
3391 Overridden->getDeclContext());
3392 if (NNS) {
3393 std::string Str;
3394 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003395 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003396 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003397 }
3398 } else if (!InContext->Equals(Overridden->getDeclContext()))
3399 continue;
3400
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003401 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003402 Overridden->getNameAsString()));
3403 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003404 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003405 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003406 if (FirstParam)
3407 FirstParam = false;
3408 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003409 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003410
Aaron Ballman43b68be2014-03-07 17:50:17 +00003411 Builder.AddPlaceholderChunk(
3412 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003413 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003414 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3415 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003416 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003417 CXCursor_CXXMethod,
3418 CXAvailability_Available,
3419 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003420 Results.Ignore(Overridden);
3421 }
3422}
3423
Douglas Gregor07f43572012-01-29 18:15:03 +00003424void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3425 ModuleIdPath Path) {
3426 typedef CodeCompletionResult Result;
3427 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003428 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003429 CodeCompletionContext::CCC_Other);
3430 Results.EnterNewScope();
3431
3432 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003433 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003434 typedef CodeCompletionResult Result;
3435 if (Path.empty()) {
3436 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003437 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003438 PP.getHeaderSearchInfo().collectAllModules(Modules);
3439 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3440 Builder.AddTypedTextChunk(
3441 Builder.getAllocator().CopyString(Modules[I]->Name));
3442 Results.AddResult(Result(Builder.TakeString(),
3443 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003444 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003445 Modules[I]->isAvailable()
3446 ? CXAvailability_Available
3447 : CXAvailability_NotAvailable));
3448 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003449 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003450 // Load the named module.
3451 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3452 Module::AllVisible,
3453 /*IsInclusionDirective=*/false);
3454 // Enumerate submodules.
3455 if (Mod) {
3456 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3457 SubEnd = Mod->submodule_end();
3458 Sub != SubEnd; ++Sub) {
3459
3460 Builder.AddTypedTextChunk(
3461 Builder.getAllocator().CopyString((*Sub)->Name));
3462 Results.AddResult(Result(Builder.TakeString(),
3463 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003464 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003465 (*Sub)->isAvailable()
3466 ? CXAvailability_Available
3467 : CXAvailability_NotAvailable));
3468 }
3469 }
3470 }
3471 Results.ExitScope();
3472 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3473 Results.data(),Results.size());
3474}
3475
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003476void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003477 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003478 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003479 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003480 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003481 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003482
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003483 // Determine how to filter results, e.g., so that the names of
3484 // values (functions, enumerators, function templates, etc.) are
3485 // only allowed where we can have an expression.
3486 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003487 case PCC_Namespace:
3488 case PCC_Class:
3489 case PCC_ObjCInterface:
3490 case PCC_ObjCImplementation:
3491 case PCC_ObjCInstanceVariableList:
3492 case PCC_Template:
3493 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003494 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003495 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003496 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3497 break;
3498
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003499 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003500 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003501 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003502 case PCC_ForInit:
3503 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003504 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003505 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3506 else
3507 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003508
David Blaikiebbafb8a2012-03-11 07:00:24 +00003509 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003510 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003511 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003512
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003513 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003514 // Unfiltered
3515 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003516 }
3517
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003518 // If we are in a C++ non-static member function, check the qualifiers on
3519 // the member function to filter/prioritize the results list.
3520 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3521 if (CurMethod->isInstance())
3522 Results.setObjectTypeQualifiers(
3523 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3524
Douglas Gregorc580c522010-01-14 01:09:38 +00003525 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003526 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3527 CodeCompleter->includeGlobals());
Douglas Gregor92253692009-12-07 09:54:55 +00003528
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003529 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003530 Results.ExitScope();
3531
Douglas Gregorce0e8562010-08-23 21:54:33 +00003532 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003533 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003534 case PCC_Expression:
3535 case PCC_Statement:
3536 case PCC_RecoveryInFunction:
3537 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003538 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003539 break;
3540
3541 case PCC_Namespace:
3542 case PCC_Class:
3543 case PCC_ObjCInterface:
3544 case PCC_ObjCImplementation:
3545 case PCC_ObjCInstanceVariableList:
3546 case PCC_Template:
3547 case PCC_MemberTemplate:
3548 case PCC_ForInit:
3549 case PCC_Condition:
3550 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003551 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003552 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003553 }
3554
Douglas Gregor9eb77012009-11-07 00:00:49 +00003555 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003556 AddMacroResults(PP, Results, false);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003557
Douglas Gregor50832e02010-09-20 22:39:41 +00003558 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003559 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003560}
3561
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003562static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3563 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003564 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003565 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003566 bool IsSuper,
3567 ResultBuilder &Results);
3568
3569void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3570 bool AllowNonIdentifiers,
3571 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003572 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003573 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003574 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003575 AllowNestedNameSpecifiers
3576 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3577 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003578 Results.EnterNewScope();
3579
3580 // Type qualifiers can come after names.
3581 Results.AddResult(Result("const"));
3582 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003583 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003584 Results.AddResult(Result("restrict"));
3585
David Blaikiebbafb8a2012-03-11 07:00:24 +00003586 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003587 if (getLangOpts().CPlusPlus11 &&
3588 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3589 DS.getTypeSpecType() == DeclSpec::TST_struct))
3590 Results.AddResult("final");
3591
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003592 if (AllowNonIdentifiers) {
3593 Results.AddResult(Result("operator"));
3594 }
3595
3596 // Add nested-name-specifiers.
3597 if (AllowNestedNameSpecifiers) {
3598 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003599 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003600 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3601 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3602 CodeCompleter->includeGlobals());
Craig Topperc3ec1492014-05-26 06:22:03 +00003603 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003604 }
3605 }
3606 Results.ExitScope();
3607
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003608 // If we're in a context where we might have an expression (rather than a
3609 // declaration), and what we've seen so far is an Objective-C type that could
3610 // be a receiver of a class message, this may be a class message send with
3611 // the initial opening bracket '[' missing. Add appropriate completions.
3612 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003613 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003614 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003615 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3616 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003617 !DS.isTypeAltiVecVector() &&
3618 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003619 (S->getFlags() & Scope::DeclScope) != 0 &&
3620 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3621 Scope::FunctionPrototypeScope |
3622 Scope::AtCatchScope)) == 0) {
3623 ParsedType T = DS.getRepAsType();
3624 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003625 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003626 }
3627
Douglas Gregor56ccce02010-08-24 04:59:56 +00003628 // Note that we intentionally suppress macro results here, since we do not
3629 // encourage using macros to produce the names of entities.
3630
Douglas Gregor0ac41382010-09-23 23:01:17 +00003631 HandleCodeCompleteResults(this, CodeCompleter,
3632 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003633 Results.data(), Results.size());
3634}
3635
Douglas Gregor68762e72010-08-23 21:17:50 +00003636struct Sema::CodeCompleteExpressionData {
3637 CodeCompleteExpressionData(QualType PreferredType = QualType())
3638 : PreferredType(PreferredType), IntegralConstantExpression(false),
3639 ObjCCollection(false) { }
3640
3641 QualType PreferredType;
3642 bool IntegralConstantExpression;
3643 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003644 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003645};
3646
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003647/// \brief Perform code-completion in an expression context when we know what
3648/// type we're looking for.
Douglas Gregor68762e72010-08-23 21:17:50 +00003649void Sema::CodeCompleteExpression(Scope *S,
3650 const CodeCompleteExpressionData &Data) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003651 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003652 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003653 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003654 if (Data.ObjCCollection)
3655 Results.setFilter(&ResultBuilder::IsObjCCollection);
3656 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003657 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003658 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003659 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3660 else
3661 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003662
3663 if (!Data.PreferredType.isNull())
3664 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3665
3666 // Ignore any declarations that we were told that we don't care about.
3667 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3668 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003669
3670 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003671 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3672 CodeCompleter->includeGlobals());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003673
3674 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003675 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003676 Results.ExitScope();
3677
Douglas Gregor55b037b2010-07-08 20:55:51 +00003678 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003679 if (!Data.PreferredType.isNull())
3680 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3681 || Data.PreferredType->isMemberPointerType()
3682 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003683
Douglas Gregorce0e8562010-08-23 21:54:33 +00003684 if (S->getFnParent() &&
3685 !Data.ObjCCollection &&
3686 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003687 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003688
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003689 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003690 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003691 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003692 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3693 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003694 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003695}
3696
Douglas Gregoreda7e542010-09-18 01:28:11 +00003697void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3698 if (E.isInvalid())
3699 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003700 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003701 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003702}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003703
Douglas Gregorb888acf2010-12-09 23:01:55 +00003704/// \brief The set of properties that have already been added, referenced by
3705/// property name.
3706typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3707
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003708/// \brief Retrieve the container definition, if any?
3709static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3710 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3711 if (Interface->hasDefinition())
3712 return Interface->getDefinition();
3713
3714 return Interface;
3715 }
3716
3717 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3718 if (Protocol->hasDefinition())
3719 return Protocol->getDefinition();
3720
3721 return Protocol;
3722 }
3723 return Container;
3724}
3725
Alex Lorenzbaef8022016-11-09 13:43:18 +00003726/// \brief Adds a block invocation code completion result for the given block
3727/// declaration \p BD.
3728static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3729 CodeCompletionBuilder &Builder,
3730 const NamedDecl *BD,
3731 const FunctionTypeLoc &BlockLoc,
3732 const FunctionProtoTypeLoc &BlockProtoLoc) {
3733 Builder.AddResultTypeChunk(
3734 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3735 Policy, Builder.getAllocator()));
3736
3737 AddTypedNameChunk(Context, Policy, BD, Builder);
3738 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3739
3740 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3741 Builder.AddPlaceholderChunk("...");
3742 } else {
3743 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3744 if (I)
3745 Builder.AddChunk(CodeCompletionString::CK_Comma);
3746
3747 // Format the placeholder string.
3748 std::string PlaceholderStr =
3749 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3750
3751 if (I == N - 1 && BlockProtoLoc &&
3752 BlockProtoLoc.getTypePtr()->isVariadic())
3753 PlaceholderStr += ", ...";
3754
3755 // Add the placeholder string.
3756 Builder.AddPlaceholderChunk(
3757 Builder.getAllocator().CopyString(PlaceholderStr));
3758 }
3759 }
3760
3761 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3762}
3763
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003764static void AddObjCProperties(
3765 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3766 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3767 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3768 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003769 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003770
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003771 // Retrieve the definition.
3772 Container = getContainerDef(Container);
3773
Douglas Gregor9291bad2009-11-18 01:29:26 +00003774 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003775 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003776 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003777 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003778
Alex Lorenzbaef8022016-11-09 13:43:18 +00003779 // FIXME: Provide block invocation completion for non-statement
3780 // expressions.
3781 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3782 !IsBaseExprStatement) {
3783 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3784 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003785 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003786 }
3787
3788 // Block setter and invocation completion is provided only when we are able
3789 // to find the FunctionProtoTypeLoc with parameter names for the block.
3790 FunctionTypeLoc BlockLoc;
3791 FunctionProtoTypeLoc BlockProtoLoc;
3792 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3793 BlockProtoLoc);
3794 if (!BlockLoc) {
3795 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3796 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003797 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003798 }
3799
3800 // The default completion result for block properties should be the block
3801 // invocation completion when the base expression is a statement.
3802 CodeCompletionBuilder Builder(Results.getAllocator(),
3803 Results.getCodeCompletionTUInfo());
3804 AddObjCBlockCall(Container->getASTContext(),
3805 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3806 BlockLoc, BlockProtoLoc);
3807 Results.MaybeAddResult(
3808 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3809 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003810
3811 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003812 // statement and the block property is mutable.
3813 if (!P->isReadOnly()) {
3814 CodeCompletionBuilder Builder(Results.getAllocator(),
3815 Results.getCodeCompletionTUInfo());
3816 AddResultTypeChunk(Container->getASTContext(),
3817 getCompletionPrintingPolicy(Results.getSema()), P,
3818 CCContext.getBaseType(), Builder);
3819 Builder.AddTypedTextChunk(
3820 Results.getAllocator().CopyString(P->getName()));
3821 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003822
Alex Lorenzbaef8022016-11-09 13:43:18 +00003823 std::string PlaceholderStr = formatBlockPlaceholder(
3824 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3825 BlockProtoLoc, /*SuppressBlockName=*/true);
3826 // Add the placeholder string.
3827 Builder.AddPlaceholderChunk(
3828 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003829
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003830 // When completing blocks properties that return void the default
3831 // property completion result should show up before the setter,
3832 // otherwise the setter completion should show up before the default
3833 // property completion, as we normally want to use the result of the
3834 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00003835 Results.MaybeAddResult(
3836 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003837 Results.getBasePriority(P) +
3838 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
3839 ? CCD_BlockPropertySetter
3840 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00003841 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003842 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003843 };
3844
3845 if (IsClassProperty) {
3846 for (const auto *P : Container->class_properties())
3847 AddProperty(P);
3848 } else {
3849 for (const auto *P : Container->instance_properties())
3850 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003851 }
Craig Topperc3ec1492014-05-26 06:22:03 +00003852
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003853 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00003854 if (AllowNullaryMethods) {
3855 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003856 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003857 // Adds a method result
3858 const auto AddMethod = [&](const ObjCMethodDecl *M) {
3859 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
3860 if (!Name)
3861 return;
3862 if (!AddedProperties.insert(Name).second)
3863 return;
3864 CodeCompletionBuilder Builder(Results.getAllocator(),
3865 Results.getCodeCompletionTUInfo());
3866 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
3867 Builder.AddTypedTextChunk(
3868 Results.getAllocator().CopyString(Name->getName()));
3869 Results.MaybeAddResult(
3870 Result(Builder.TakeString(), M,
3871 CCP_MemberDeclaration + CCD_MethodAsProperty),
3872 CurContext);
3873 };
3874
3875 if (IsClassProperty) {
3876 for (const auto *M : Container->methods()) {
3877 // Gather the class method that can be used as implicit property
3878 // getters. Methods with arguments or methods that return void aren't
3879 // added to the results as they can't be used as a getter.
3880 if (!M->getSelector().isUnarySelector() ||
3881 M->getReturnType()->isVoidType() || M->isInstanceMethod())
3882 continue;
3883 AddMethod(M);
3884 }
3885 } else {
3886 for (auto *M : Container->methods()) {
3887 if (M->getSelector().isUnarySelector())
3888 AddMethod(M);
3889 }
Douglas Gregor95147142011-05-05 15:50:42 +00003890 }
3891 }
Douglas Gregor95147142011-05-05 15:50:42 +00003892
Douglas Gregor9291bad2009-11-18 01:29:26 +00003893 // Add properties in referenced protocols.
3894 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003895 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003896 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003897 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003898 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003899 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003900 if (AllowCategories) {
3901 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00003902 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003903 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003904 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003905 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00003906 }
Aaron Ballman15063e12014-03-13 21:35:02 +00003907
Douglas Gregor9291bad2009-11-18 01:29:26 +00003908 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003909 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003910 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003911 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003912 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003913
Douglas Gregor9291bad2009-11-18 01:29:26 +00003914 // Look in the superclass.
3915 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003916 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003917 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003918 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003919 } else if (const ObjCCategoryDecl *Category
3920 = dyn_cast<ObjCCategoryDecl>(Container)) {
3921 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00003922 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003923 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003924 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003925 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003926 }
3927}
3928
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003929static void AddRecordMembersCompletionResults(Sema &SemaRef,
3930 ResultBuilder &Results, Scope *S,
3931 QualType BaseType,
3932 RecordDecl *RD) {
3933 // Indicate that we are performing a member access, and the cv-qualifiers
3934 // for the base object type.
3935 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3936
3937 // Access to a C/C++ class, struct, or union.
3938 Results.allowNestedNameSpecifiers();
3939 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
3940 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00003941 SemaRef.CodeCompleter->includeGlobals(),
3942 /*IncludeDependentBases=*/true);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003943
3944 if (SemaRef.getLangOpts().CPlusPlus) {
3945 if (!Results.empty()) {
3946 // The "template" keyword can follow "->" or "." in the grammar.
3947 // However, we only want to suggest the template keyword if something
3948 // is dependent.
3949 bool IsDependent = BaseType->isDependentType();
3950 if (!IsDependent) {
3951 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3952 if (DeclContext *Ctx = DepScope->getEntity()) {
3953 IsDependent = Ctx->isDependentContext();
3954 break;
3955 }
3956 }
3957
3958 if (IsDependent)
3959 Results.AddResult(CodeCompletionResult("template"));
3960 }
3961 }
3962}
3963
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003964void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003965 SourceLocation OpLoc, bool IsArrow,
3966 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003967 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003968 return;
3969
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003970 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3971 if (ConvertedBase.isInvalid())
3972 return;
3973 Base = ConvertedBase.get();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003974
Douglas Gregor2436e712009-09-17 21:32:03 +00003975 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003976
3977 if (IsArrow) {
3978 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3979 BaseType = Ptr->getPointeeType();
3980 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003981 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003982 else
3983 return;
3984 }
3985
Douglas Gregor21325842011-07-07 16:03:39 +00003986 enum CodeCompletionContext::Kind contextKind;
3987
3988 if (IsArrow) {
3989 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3990 }
3991 else {
3992 if (BaseType->isObjCObjectPointerType() ||
3993 BaseType->isObjCObjectOrInterfaceType()) {
3994 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3995 }
3996 else {
3997 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3998 }
3999 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004000
4001 CodeCompletionContext CCContext(contextKind, BaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004002 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004003 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00004004 CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004005 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004006 Results.EnterNewScope();
4007 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004008 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4009 Record->getDecl());
Alex Lorenze6afa392017-05-11 13:48:57 +00004010 } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
4011 TemplateName TN = TST->getTemplateName();
4012 if (const auto *TD =
4013 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4014 CXXRecordDecl *RD = TD->getTemplatedDecl();
4015 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
4016 }
4017 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4018 if (auto *RD = ICNT->getDecl())
4019 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
Alex Lorenz06cfa992016-10-12 11:40:15 +00004020 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004021 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00004022 AddedPropertiesSet AddedProperties;
Alex Lorenz06cfa992016-10-12 11:40:15 +00004023
4024 if (const ObjCObjectPointerType *ObjCPtr =
4025 BaseType->getAsObjCInterfacePointerType()) {
4026 // Add property results based on our interface.
4027 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4028 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4029 /*AllowNullaryMethods=*/true, CurContext,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004030 AddedProperties, Results, IsBaseExprStatement);
Alex Lorenz06cfa992016-10-12 11:40:15 +00004031 }
4032
Douglas Gregor9291bad2009-11-18 01:29:26 +00004033 // Add properties from the protocols in a qualified interface.
Alex Lorenz06cfa992016-10-12 11:40:15 +00004034 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004035 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004036 CurContext, AddedProperties, Results,
4037 IsBaseExprStatement);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004038 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00004039 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004040 // Objective-C instance variable access.
Craig Topperc3ec1492014-05-26 06:22:03 +00004041 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004042 if (const ObjCObjectPointerType *ObjCPtr
4043 = BaseType->getAs<ObjCObjectPointerType>())
4044 Class = ObjCPtr->getInterfaceDecl();
4045 else
John McCall8b07ec22010-05-15 11:32:37 +00004046 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00004047
4048 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00004049 if (Class) {
4050 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4051 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor39982192010-08-15 06:18:01 +00004052 LookupVisibleDecls(Class, LookupMemberName, Consumer,
4053 CodeCompleter->includeGlobals());
Douglas Gregor9291bad2009-11-18 01:29:26 +00004054 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004055 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00004056
4057 // FIXME: How do we cope with isa?
4058
4059 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004060
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004061 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004062 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004063 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004064 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004065}
4066
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004067void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4068 IdentifierInfo &ClassName,
4069 SourceLocation ClassNameLoc,
4070 bool IsBaseExprStatement) {
4071 IdentifierInfo *ClassNamePtr = &ClassName;
4072 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4073 if (!IFace)
4074 return;
4075 CodeCompletionContext CCContext(
4076 CodeCompletionContext::CCC_ObjCPropertyAccess);
4077 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4078 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4079 &ResultBuilder::IsMember);
4080 Results.EnterNewScope();
4081 AddedPropertiesSet AddedProperties;
4082 AddObjCProperties(CCContext, IFace, true,
4083 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4084 Results, IsBaseExprStatement,
4085 /*IsClassProperty=*/true);
4086 Results.ExitScope();
4087 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4088 Results.data(), Results.size());
4089}
4090
Faisal Vali090da2d2018-01-01 18:23:28 +00004091void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004092 if (!CodeCompleter)
4093 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004094
4095 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004096 enum CodeCompletionContext::Kind ContextKind
4097 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004098 switch ((DeclSpec::TST)TagSpec) {
4099 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004100 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004101 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004102 break;
4103
4104 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004105 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004106 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004107 break;
4108
4109 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004110 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004111 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004112 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004113 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004114 break;
4115
4116 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004117 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004118 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004119
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004120 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4121 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004122 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004123
4124 // First pass: look for tags.
4125 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004126 LookupVisibleDecls(S, LookupTagName, Consumer,
4127 CodeCompleter->includeGlobals());
John McCalle87beb22010-04-23 18:46:30 +00004128
Douglas Gregor39982192010-08-15 06:18:01 +00004129 if (CodeCompleter->includeGlobals()) {
4130 // Second pass: look for nested name specifiers.
4131 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
4132 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
4133 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004134
Douglas Gregor0ac41382010-09-23 23:01:17 +00004135 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004136 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004137}
4138
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004139static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4140 const LangOptions &LangOpts) {
4141 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4142 Results.AddResult("const");
4143 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4144 Results.AddResult("volatile");
4145 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4146 Results.AddResult("restrict");
4147 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4148 Results.AddResult("_Atomic");
4149 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4150 Results.AddResult("__unaligned");
4151}
4152
Douglas Gregor28c78432010-08-27 17:35:51 +00004153void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004154 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004155 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004156 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004157 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004158 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004159 Results.ExitScope();
4160 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004161 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004162 Results.data(), Results.size());
4163}
4164
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004165void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4166 const VirtSpecifiers *VS) {
4167 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4168 CodeCompleter->getCodeCompletionTUInfo(),
4169 CodeCompletionContext::CCC_TypeQualifiers);
4170 Results.EnterNewScope();
4171 AddTypeQualifierResults(DS, Results, LangOpts);
4172 if (LangOpts.CPlusPlus11) {
4173 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004174 if (D.getContext() == DeclaratorContext::MemberContext &&
4175 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004176 if (!VS || !VS->isFinalSpecified())
4177 Results.AddResult("final");
4178 if (!VS || !VS->isOverrideSpecified())
4179 Results.AddResult("override");
4180 }
4181 }
4182 Results.ExitScope();
4183 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4184 Results.data(), Results.size());
4185}
4186
Benjamin Kramer72dae622016-02-18 15:30:24 +00004187void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4188 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4189}
4190
Douglas Gregord328d572009-09-21 18:10:23 +00004191void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004192 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004193 return;
John McCall5939b162011-08-06 07:30:58 +00004194
John McCallaab3e412010-08-25 08:40:02 +00004195 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00004196 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4197 if (!type->isEnumeralType()) {
4198 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004199 Data.IntegralConstantExpression = true;
4200 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004201 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004202 }
Douglas Gregord328d572009-09-21 18:10:23 +00004203
4204 // Code-complete the cases of a switch statement over an enumeration type
4205 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004206 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004207 if (EnumDecl *Def = Enum->getDefinition())
4208 Enum = Def;
Douglas Gregord328d572009-09-21 18:10:23 +00004209
4210 // Determine which enumerators we have already seen in the switch statement.
4211 // FIXME: Ideally, we would also be able to look *past* the code-completion
4212 // token, in case we are code-completing in the middle of the switch and not
4213 // at the end. However, we aren't able to do so at the moment.
4214 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004215 NestedNameSpecifier *Qualifier = nullptr;
Douglas Gregord328d572009-09-21 18:10:23 +00004216 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
4217 SC = SC->getNextSwitchCase()) {
4218 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4219 if (!Case)
4220 continue;
4221
4222 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4223 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4224 if (EnumConstantDecl *Enumerator
4225 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
4226 // We look into the AST of the case statement to determine which
4227 // enumerator was named. Alternatively, we could compute the value of
4228 // the integral constant expression, then compare it against the
4229 // values of each enumerator. However, value-based approach would not
4230 // work as well with C++ templates where enumerators declared within a
4231 // template are type- and value-dependent.
4232 EnumeratorsSeen.insert(Enumerator);
4233
Douglas Gregorf2510672009-09-21 19:57:38 +00004234 // If this is a qualified-id, keep track of the nested-name-specifier
4235 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004236 //
4237 // switch (TagD.getKind()) {
4238 // case TagDecl::TK_enum:
4239 // break;
4240 // case XXX
4241 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004242 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004243 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4244 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004245 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004246 }
4247 }
4248
David Blaikiebbafb8a2012-03-11 07:00:24 +00004249 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00004250 // If there are no prior enumerators in C++, check whether we have to
4251 // qualify the names of the enumerators that we suggest, because they
4252 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004253 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004254 }
4255
Douglas Gregord328d572009-09-21 18:10:23 +00004256 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004257 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004258 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004259 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004260 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004261 for (auto *E : Enum->enumerators()) {
4262 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004263 continue;
4264
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004265 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004266 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004267 }
4268 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004269
Douglas Gregor21325842011-07-07 16:03:39 +00004270 //We need to make sure we're setting the right context,
4271 //so only say we include macros if the code completer says we do
4272 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
4273 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00004274 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00004275 kind = CodeCompletionContext::CCC_OtherWithMacros;
4276 }
4277
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004278 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00004279 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004280 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004281}
4282
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004283static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004284 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004285 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004286
4287 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004288 if (!Args[I])
4289 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004290
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004291 return false;
4292}
4293
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004294typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4295
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004296static void mergeCandidatesWithResults(Sema &SemaRef,
4297 SmallVectorImpl<ResultCandidate> &Results,
4298 OverloadCandidateSet &CandidateSet,
4299 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004300 if (!CandidateSet.empty()) {
4301 // Sort the overload candidate set by placing the best overloads first.
4302 std::stable_sort(
4303 CandidateSet.begin(), CandidateSet.end(),
4304 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004305 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4306 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004307 });
4308
4309 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004310 for (auto &Candidate : CandidateSet) {
4311 if (Candidate.Function && Candidate.Function->isDeleted())
4312 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004313 if (Candidate.Viable)
4314 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004315 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004316 }
4317}
4318
4319/// \brief Get the type of the Nth parameter from a given set of overload
4320/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004321static QualType getParamType(Sema &SemaRef,
4322 ArrayRef<ResultCandidate> Candidates,
4323 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004324
4325 // Given the overloads 'Candidates' for a function call matching all arguments
4326 // up to N, return the type of the Nth parameter if it is the same for all
4327 // overload candidates.
4328 QualType ParamType;
4329 for (auto &Candidate : Candidates) {
4330 if (auto FType = Candidate.getFunctionType())
4331 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4332 if (N < Proto->getNumParams()) {
4333 if (ParamType.isNull())
4334 ParamType = Proto->getParamType(N);
4335 else if (!SemaRef.Context.hasSameUnqualifiedType(
4336 ParamType.getNonReferenceType(),
4337 Proto->getParamType(N).getNonReferenceType()))
4338 // Otherwise return a default-constructed QualType.
4339 return QualType();
4340 }
4341 }
4342
4343 return ParamType;
4344}
4345
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004346static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
4347 MutableArrayRef<ResultCandidate> Candidates,
4348 unsigned CurrentArg,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004349 bool CompleteExpressionWithCurrentArg = true) {
4350 QualType ParamType;
4351 if (CompleteExpressionWithCurrentArg)
4352 ParamType = getParamType(SemaRef, Candidates, CurrentArg);
4353
4354 if (ParamType.isNull())
4355 SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
4356 else
4357 SemaRef.CodeCompleteExpression(S, ParamType);
4358
4359 if (!Candidates.empty())
4360 SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
4361 Candidates.data(),
4362 Candidates.size());
4363}
4364
4365void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004366 if (!CodeCompleter)
4367 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004368
4369 // When we're code-completing for a call, we fall back to ordinary
4370 // name code-completion whenever we can't produce specific
4371 // results. We may want to revisit this strategy in the future,
4372 // e.g., by merging the two kinds of results.
4373
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004374 // FIXME: Provide support for variadic template functions.
Douglas Gregor3ef59522009-12-11 19:06:04 +00004375
Douglas Gregorcabea402009-09-22 15:41:20 +00004376 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004377 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4378 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004379 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00004380 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004381 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004382
John McCall57500772009-12-16 12:17:52 +00004383 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004384 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004385 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004386
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004387 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004388
John McCall57500772009-12-16 12:17:52 +00004389 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004390 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004391 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004392 /*PartialOverloading=*/true);
4393 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4394 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4395 if (UME->hasExplicitTemplateArgs()) {
4396 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4397 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004398 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004399
4400 // Add the base as first argument (use a nullptr if the base is implicit).
4401 SmallVector<Expr *, 12> ArgExprs(
4402 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004403 ArgExprs.append(Args.begin(), Args.end());
4404 UnresolvedSet<8> Decls;
4405 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004406 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004407 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4408 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004409 /*PartialOverloading=*/true,
4410 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004411 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004412 FunctionDecl *FD = nullptr;
4413 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4414 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4415 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4416 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004417 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004418 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004419 !FD->getType()->getAs<FunctionProtoType>())
4420 Results.push_back(ResultCandidate(FD));
4421 else
4422 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4423 Args, CandidateSet,
4424 /*SuppressUsedConversions=*/false,
4425 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004426
4427 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4428 // If expression's type is CXXRecordDecl, it may overload the function
4429 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004430 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004431 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004432 DeclarationName OpName = Context.DeclarationNames
4433 .getCXXOperatorName(OO_Call);
4434 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4435 LookupQualifiedName(R, DC);
4436 R.suppressDiagnostics();
4437 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4438 ArgExprs.append(Args.begin(), Args.end());
4439 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4440 /*ExplicitArgs=*/nullptr,
4441 /*SuppressUsedConversions=*/false,
4442 /*PartialOverloading=*/true);
4443 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004444 } else {
4445 // Lastly we check whether expression's type is function pointer or
4446 // function.
4447 QualType T = NakedFn->getType();
4448 if (!T->getPointeeType().isNull())
4449 T = T->getPointeeType();
4450
4451 if (auto FP = T->getAs<FunctionProtoType>()) {
4452 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004453 /*PartialOverloading=*/true) ||
4454 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004455 Results.push_back(ResultCandidate(FP));
4456 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004457 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004458 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004459 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004460 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00004461
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004462 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4463 CodeCompleteOverloadResults(*this, S, Results, Args.size(),
4464 !CandidateSet.empty());
4465}
4466
4467void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
4468 ArrayRef<Expr *> Args) {
4469 if (!CodeCompleter)
4470 return;
4471
4472 // A complete type is needed to lookup for constructors.
Richard Smithdb0ac552015-12-18 22:40:25 +00004473 if (!isCompleteType(Loc, Type))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004474 return;
4475
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004476 CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
4477 if (!RD) {
4478 CodeCompleteExpression(S, Type);
4479 return;
4480 }
4481
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004482 // FIXME: Provide support for member initializers.
4483 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004484
4485 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4486
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004487 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004488 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4489 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4490 Args, CandidateSet,
4491 /*SuppressUsedConversions=*/false,
4492 /*PartialOverloading=*/true);
4493 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4494 AddTemplateOverloadCandidate(FTD,
4495 DeclAccessPair::make(FTD, C->getAccess()),
4496 /*ExplicitTemplateArgs=*/nullptr,
4497 Args, CandidateSet,
4498 /*SuppressUsedConversions=*/false,
4499 /*PartialOverloading=*/true);
4500 }
4501 }
4502
4503 SmallVector<ResultCandidate, 8> Results;
4504 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4505 CodeCompleteOverloadResults(*this, S, Results, Args.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00004506}
4507
John McCall48871652010-08-21 09:40:31 +00004508void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4509 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004510 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004511 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004512 return;
4513 }
4514
4515 CodeCompleteExpression(S, VD->getType());
4516}
4517
4518void Sema::CodeCompleteReturn(Scope *S) {
4519 QualType ResultType;
4520 if (isa<BlockDecl>(CurContext)) {
4521 if (BlockScopeInfo *BSI = getCurBlock())
4522 ResultType = BSI->ReturnType;
4523 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004524 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004525 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004526 ResultType = Method->getReturnType();
4527
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004528 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004529 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004530 else
4531 CodeCompleteExpression(S, ResultType);
4532}
4533
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004534void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004535 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004536 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004537 mapCodeCompletionContext(*this, PCC_Statement));
4538 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4539 Results.EnterNewScope();
4540
4541 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4542 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4543 CodeCompleter->includeGlobals());
4544
4545 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
4546
4547 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004548 CodeCompletionBuilder Builder(Results.getAllocator(),
4549 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004550 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004551 if (Results.includeCodePatterns()) {
4552 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4553 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4554 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4555 Builder.AddPlaceholderChunk("statements");
4556 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4557 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4558 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004559 Results.AddResult(Builder.TakeString());
4560
4561 // "else if" block
4562 Builder.AddTypedTextChunk("else");
4563 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4564 Builder.AddTextChunk("if");
4565 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4566 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004567 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004568 Builder.AddPlaceholderChunk("condition");
4569 else
4570 Builder.AddPlaceholderChunk("expression");
4571 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004572 if (Results.includeCodePatterns()) {
4573 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4574 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4575 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4576 Builder.AddPlaceholderChunk("statements");
4577 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4578 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4579 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004580 Results.AddResult(Builder.TakeString());
4581
4582 Results.ExitScope();
4583
4584 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004585 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004586
4587 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004588 AddMacroResults(PP, Results, false);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004589
4590 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4591 Results.data(),Results.size());
4592}
4593
Richard Trieu2bd04012011-09-09 02:00:50 +00004594void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004595 if (LHS)
4596 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4597 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004598 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004599}
4600
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004601void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004602 bool EnteringContext) {
Eric Liu06d34022017-12-12 11:35:46 +00004603 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004604 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004605
Eric Liu06d34022017-12-12 11:35:46 +00004606 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4607 // "a::b::" is not corresponding to any context/namespace in the AST), since
4608 // it can be useful for global code completion which have information about
4609 // contexts/symbols that are not in the AST.
4610 if (SS.isInvalid()) {
4611 CodeCompletionContext CC(CodeCompletionContext::CCC_Name);
4612 CC.setCXXScopeSpecifier(SS);
4613 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4614 return;
4615 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004616 // Always pretend to enter a context to ensure that a dependent type
4617 // resolves to a dependent record.
4618 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004619 if (!Ctx)
4620 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004621
4622 // Try to instantiate any non-dependent declaration contexts before
4623 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004624 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004625 return;
4626
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004627 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004628 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004629 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004630 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004631
Douglas Gregor3545ff42009-09-21 16:56:56 +00004632 // The "template" keyword can follow "::" in the grammar, but only
4633 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004634 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004635 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004636 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004637
4638 // Add calls to overridden virtual functions, if there are any.
4639 //
4640 // FIXME: This isn't wonderful, because we don't know whether we're actually
4641 // in a context that permits expressions. This is a general issue with
4642 // qualified-id completions.
4643 if (!EnteringContext)
4644 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004645 Results.ExitScope();
4646
Eric Liufead6ae2017-12-13 10:26:49 +00004647 if (CodeCompleter->includeNamespaceLevelDecls() ||
4648 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
4649 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4650 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4651 /*IncludeGlobalScope=*/true,
4652 /*IncludeDependentBases=*/true);
4653 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004654
Eric Liu06d34022017-12-12 11:35:46 +00004655 auto CC = Results.getCompletionContext();
4656 CC.setCXXScopeSpecifier(SS);
4657
4658 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4659 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004660}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004661
4662void Sema::CodeCompleteUsing(Scope *S) {
4663 if (!CodeCompleter)
4664 return;
4665
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004666 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004667 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004668 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4669 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004670 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004671
4672 // If we aren't in class scope, we could see the "namespace" keyword.
4673 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004674 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004675
4676 // After "using", we can see anything that would start a
4677 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004678 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004679 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4680 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004681 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004682
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004683 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004684 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004685 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004686}
4687
4688void Sema::CodeCompleteUsingDirective(Scope *S) {
4689 if (!CodeCompleter)
4690 return;
4691
Douglas Gregor3545ff42009-09-21 16:56:56 +00004692 // After "using namespace", we expect to see a namespace name or namespace
4693 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004694 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004695 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004696 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004697 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004698 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004699 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004700 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4701 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004702 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004703 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004704 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004705 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004706}
4707
4708void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4709 if (!CodeCompleter)
4710 return;
4711
Ted Kremenekc37877d2013-10-08 17:08:03 +00004712 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004713 if (!S->getParent())
4714 Ctx = Context.getTranslationUnitDecl();
4715
Douglas Gregor0ac41382010-09-23 23:01:17 +00004716 bool SuppressedGlobalResults
4717 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4718
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004719 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004720 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004721 SuppressedGlobalResults
4722 ? CodeCompletionContext::CCC_Namespace
4723 : CodeCompletionContext::CCC_Other,
4724 &ResultBuilder::IsNamespace);
4725
4726 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004727 // We only want to see those namespaces that have already been defined
4728 // within this scope, because its likely that the user is creating an
4729 // extended namespace declaration. Keep track of the most recent
4730 // definition of each namespace.
4731 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4732 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4733 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4734 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004735 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004736
4737 // Add the most recent definition (or extended definition) of each
4738 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004739 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004740 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004741 NS = OrigToLatest.begin(),
4742 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004743 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004744 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004745 NS->second, Results.getBasePriority(NS->second),
4746 nullptr),
4747 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004748 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004749 }
4750
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004751 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004752 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004753 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004754}
4755
4756void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4757 if (!CodeCompleter)
4758 return;
4759
Douglas Gregor3545ff42009-09-21 16:56:56 +00004760 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004761 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004762 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004763 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004764 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004765 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004766 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4767 CodeCompleter->includeGlobals());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004768 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004769 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004770 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004771}
4772
Douglas Gregorc811ede2009-09-18 20:05:18 +00004773void Sema::CodeCompleteOperatorName(Scope *S) {
4774 if (!CodeCompleter)
4775 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004776
John McCall276321a2010-08-25 06:19:51 +00004777 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004778 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004779 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004780 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004781 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004782 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004783
Douglas Gregor3545ff42009-09-21 16:56:56 +00004784 // Add the names of overloadable operators.
4785#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4786 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004787 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004788#include "clang/Basic/OperatorKinds.def"
4789
4790 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004791 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004792 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004793 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4794 CodeCompleter->includeGlobals());
Douglas Gregor3545ff42009-09-21 16:56:56 +00004795
4796 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004797 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004798 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004799
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004800 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004801 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004802 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004803}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004804
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004805void Sema::CodeCompleteConstructorInitializer(
4806 Decl *ConstructorD,
4807 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004808 if (!ConstructorD)
4809 return;
4810
4811 AdjustDeclIfTemplate(ConstructorD);
4812
4813 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004814 if (!Constructor)
4815 return;
4816
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004817 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004818 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004819 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004820 Results.EnterNewScope();
4821
4822 // Fill in any already-initialized fields or base classes.
4823 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4824 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004825 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004826 if (Initializers[I]->isBaseInitializer())
4827 InitializedBases.insert(
4828 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4829 else
Francois Pichetd583da02010-12-04 09:14:42 +00004830 InitializedFields.insert(cast<FieldDecl>(
4831 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004832 }
4833
4834 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004835 CodeCompletionBuilder Builder(Results.getAllocator(),
4836 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004837 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004838 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004839 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004840 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004841 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4842 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004843 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004844 = !Initializers.empty() &&
4845 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004846 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004847 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004848 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004849 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004850
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004851 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004852 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004853 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004854 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4855 Builder.AddPlaceholderChunk("args");
4856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4857 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004858 SawLastInitializer? CCP_NextInitializer
4859 : CCP_MemberDeclaration));
4860 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004861 }
4862
4863 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004864 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004865 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4866 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004867 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004868 = !Initializers.empty() &&
4869 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004870 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004871 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004872 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004873 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004874
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004875 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004876 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004877 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004878 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4879 Builder.AddPlaceholderChunk("args");
4880 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4881 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004882 SawLastInitializer? CCP_NextInitializer
4883 : CCP_MemberDeclaration));
4884 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004885 }
4886
4887 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004888 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004889 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4890 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004891 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004892 = !Initializers.empty() &&
4893 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004894 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004895 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004896 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004897
4898 if (!Field->getDeclName())
4899 continue;
4900
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004901 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004902 Field->getIdentifier()->getName()));
4903 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4904 Builder.AddPlaceholderChunk("args");
4905 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4906 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004907 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004908 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004909 CXCursor_MemberRef,
4910 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004911 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004912 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004913 }
4914 Results.ExitScope();
4915
Douglas Gregor0ac41382010-09-23 23:01:17 +00004916 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004917 Results.data(), Results.size());
4918}
4919
Douglas Gregord8c61782012-02-15 15:34:24 +00004920/// \brief Determine whether this scope denotes a namespace.
4921static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00004922 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00004923 if (!DC)
4924 return false;
4925
4926 return DC->isFileContext();
4927}
4928
4929void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4930 bool AfterAmpersand) {
4931 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004932 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00004933 CodeCompletionContext::CCC_Other);
4934 Results.EnterNewScope();
4935
4936 // Note what has already been captured.
4937 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4938 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004939 for (const auto &C : Intro.Captures) {
4940 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00004941 IncludedThis = true;
4942 continue;
4943 }
4944
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004945 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00004946 }
4947
4948 // Look for other capturable variables.
4949 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00004950 for (const auto *D : S->decls()) {
4951 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00004952 if (!Var ||
4953 !Var->hasLocalStorage() ||
4954 Var->hasAttr<BlocksAttr>())
4955 continue;
4956
David Blaikie82e95a32014-11-19 07:49:47 +00004957 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004958 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00004959 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00004960 }
4961 }
4962
4963 // Add 'this', if it would be valid.
4964 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4965 addThisCompletion(*this, Results);
4966
4967 Results.ExitScope();
4968
4969 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4970 Results.data(), Results.size());
4971}
4972
James Dennett596e4752012-06-14 03:11:41 +00004973/// Macro that optionally prepends an "@" to the string literal passed in via
4974/// Keyword, depending on whether NeedAt is true or false.
4975#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4976
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004977static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004978 ResultBuilder &Results,
4979 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004980 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004981 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004982 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004983
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004984 CodeCompletionBuilder Builder(Results.getAllocator(),
4985 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004986 if (LangOpts.ObjC2) {
4987 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00004988 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004989 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4990 Builder.AddPlaceholderChunk("property");
4991 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004992
4993 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00004994 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004995 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4996 Builder.AddPlaceholderChunk("property");
4997 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004998 }
4999}
5000
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005001static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00005002 ResultBuilder &Results,
5003 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005004 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005005
5006 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00005007 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005008
5009 if (LangOpts.ObjC2) {
5010 // @property
James Dennett596e4752012-06-14 03:11:41 +00005011 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005012
5013 // @required
James Dennett596e4752012-06-14 03:11:41 +00005014 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005015
5016 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005017 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005018 }
5019}
5020
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005021static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005022 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005023 CodeCompletionBuilder Builder(Results.getAllocator(),
5024 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005025
5026 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005027 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005028 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5029 Builder.AddPlaceholderChunk("name");
5030 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005031
Douglas Gregorf4c33342010-05-28 00:22:41 +00005032 if (Results.includeCodePatterns()) {
5033 // @interface name
5034 // FIXME: Could introduce the whole pattern, including superclasses and
5035 // such.
James Dennett596e4752012-06-14 03:11:41 +00005036 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005037 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5038 Builder.AddPlaceholderChunk("class");
5039 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005040
Douglas Gregorf4c33342010-05-28 00:22:41 +00005041 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005042 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5044 Builder.AddPlaceholderChunk("protocol");
5045 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005046
5047 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005048 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005049 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5050 Builder.AddPlaceholderChunk("class");
5051 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005052 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005053
5054 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005055 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005056 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5057 Builder.AddPlaceholderChunk("alias");
5058 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5059 Builder.AddPlaceholderChunk("class");
5060 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005061
5062 if (Results.getSema().getLangOpts().Modules) {
5063 // @import name
5064 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5065 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5066 Builder.AddPlaceholderChunk("module");
5067 Results.AddResult(Result(Builder.TakeString()));
5068 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005069}
5070
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005071void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005072 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005073 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005074 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005075 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005076 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005077 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005078 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005079 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005080 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005081 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005082 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005083 HandleCodeCompleteResults(this, CodeCompleter,
5084 CodeCompletionContext::CCC_Other,
5085 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005086}
5087
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005088static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005089 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005090 CodeCompletionBuilder Builder(Results.getAllocator(),
5091 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005092
5093 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005094 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005095 if (Results.getSema().getLangOpts().CPlusPlus ||
5096 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005097 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005098 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005099 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005100 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5101 Builder.AddPlaceholderChunk("type-name");
5102 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5103 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005104
5105 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005106 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005107 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005108 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5109 Builder.AddPlaceholderChunk("protocol-name");
5110 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5111 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005112
5113 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005114 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005115 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005116 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5117 Builder.AddPlaceholderChunk("selector");
5118 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5119 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005120
5121 // @"string"
5122 Builder.AddResultTypeChunk("NSString *");
5123 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5124 Builder.AddPlaceholderChunk("string");
5125 Builder.AddTextChunk("\"");
5126 Results.AddResult(Result(Builder.TakeString()));
5127
Douglas Gregor951de302012-07-17 23:24:47 +00005128 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005129 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005130 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005131 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005132 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5133 Results.AddResult(Result(Builder.TakeString()));
5134
Douglas Gregor951de302012-07-17 23:24:47 +00005135 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005136 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005137 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005138 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005139 Builder.AddChunk(CodeCompletionString::CK_Colon);
5140 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5141 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005142 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5143 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005144
Douglas Gregor951de302012-07-17 23:24:47 +00005145 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005146 Builder.AddResultTypeChunk("id");
5147 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005148 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005149 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5150 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005151}
5152
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005153static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005154 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005155 CodeCompletionBuilder Builder(Results.getAllocator(),
5156 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005157
Douglas Gregorf4c33342010-05-28 00:22:41 +00005158 if (Results.includeCodePatterns()) {
5159 // @try { statements } @catch ( declaration ) { statements } @finally
5160 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005161 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005162 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5163 Builder.AddPlaceholderChunk("statements");
5164 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5165 Builder.AddTextChunk("@catch");
5166 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5167 Builder.AddPlaceholderChunk("parameter");
5168 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5169 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5170 Builder.AddPlaceholderChunk("statements");
5171 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5172 Builder.AddTextChunk("@finally");
5173 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5174 Builder.AddPlaceholderChunk("statements");
5175 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5176 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005177 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005178
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005179 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005180 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005181 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5182 Builder.AddPlaceholderChunk("expression");
5183 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005184
Douglas Gregorf4c33342010-05-28 00:22:41 +00005185 if (Results.includeCodePatterns()) {
5186 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005187 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005188 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5189 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5190 Builder.AddPlaceholderChunk("expression");
5191 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5192 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5193 Builder.AddPlaceholderChunk("statements");
5194 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5195 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005196 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005197}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005198
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005199static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005200 ResultBuilder &Results,
5201 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005202 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005203 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5204 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5205 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005206 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005207 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005208}
5209
5210void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005211 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005212 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005213 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005214 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005215 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005216 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005217 HandleCodeCompleteResults(this, CodeCompleter,
5218 CodeCompletionContext::CCC_Other,
5219 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005220}
5221
5222void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005223 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005224 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005225 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005226 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005227 AddObjCStatementResults(Results, false);
5228 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005229 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005230 HandleCodeCompleteResults(this, CodeCompleter,
5231 CodeCompletionContext::CCC_Other,
5232 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005233}
5234
5235void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005236 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005237 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005238 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005239 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005240 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005241 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005242 HandleCodeCompleteResults(this, CodeCompleter,
5243 CodeCompletionContext::CCC_Other,
5244 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005245}
5246
Douglas Gregore6078da2009-11-19 00:14:45 +00005247/// \brief Determine whether the addition of the given flag to an Objective-C
5248/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005249static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005250 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005251 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005252 return true;
5253
Bill Wendling44426052012-12-20 19:22:21 +00005254 Attributes |= NewFlag;
Douglas Gregore6078da2009-11-19 00:14:45 +00005255
5256 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005257 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5258 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005259 return true;
5260
Jordan Rose53cb2f32012-08-20 20:01:13 +00005261 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005262 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005263 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005264 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005265 ObjCDeclSpec::DQ_PR_retain |
5266 ObjCDeclSpec::DQ_PR_strong |
5267 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005268 if (AssignCopyRetMask &&
5269 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005270 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005271 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005272 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005273 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5274 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005275 return true;
5276
5277 return false;
5278}
5279
Douglas Gregor36029f42009-11-18 23:08:07 +00005280void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005281 if (!CodeCompleter)
5282 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005283
Bill Wendling44426052012-12-20 19:22:21 +00005284 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroff936354c2009-10-08 21:55:05 +00005285
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005286 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005287 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005288 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005289 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005290 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005291 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005292 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005293 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005294 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005295 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5296 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005297 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005298 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005299 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005300 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005301 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005302 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005303 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005304 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005305 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005306 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005307 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005308 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005309
5310 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005311 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005312 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005313 Results.AddResult(CodeCompletionResult("weak"));
5314
Bill Wendling44426052012-12-20 19:22:21 +00005315 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005316 CodeCompletionBuilder Setter(Results.getAllocator(),
5317 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005318 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005319 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005320 Setter.AddPlaceholderChunk("method");
5321 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005322 }
Bill Wendling44426052012-12-20 19:22:21 +00005323 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005324 CodeCompletionBuilder Getter(Results.getAllocator(),
5325 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005326 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005327 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005328 Getter.AddPlaceholderChunk("method");
5329 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005330 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005331 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5332 Results.AddResult(CodeCompletionResult("nonnull"));
5333 Results.AddResult(CodeCompletionResult("nullable"));
5334 Results.AddResult(CodeCompletionResult("null_unspecified"));
5335 Results.AddResult(CodeCompletionResult("null_resettable"));
5336 }
Steve Naroff936354c2009-10-08 21:55:05 +00005337 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005338 HandleCodeCompleteResults(this, CodeCompleter,
5339 CodeCompletionContext::CCC_Other,
5340 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005341}
Steve Naroffeae65032009-11-07 02:08:14 +00005342
James Dennettf1243872012-06-17 05:33:25 +00005343/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005344/// via code completion.
5345enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005346 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5347 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5348 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005349};
5350
Douglas Gregor67c692c2010-08-26 15:07:07 +00005351static bool isAcceptableObjCSelector(Selector Sel,
5352 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005353 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005354 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005355 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005356 if (NumSelIdents > Sel.getNumArgs())
5357 return false;
5358
5359 switch (WantKind) {
5360 case MK_Any: break;
5361 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5362 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5363 }
5364
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005365 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5366 return false;
5367
Douglas Gregor67c692c2010-08-26 15:07:07 +00005368 for (unsigned I = 0; I != NumSelIdents; ++I)
5369 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5370 return false;
5371
5372 return true;
5373}
5374
Douglas Gregorc8537c52009-11-19 07:41:15 +00005375static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5376 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005377 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005378 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005379 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005380 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005381}
Douglas Gregor1154e272010-09-16 16:06:31 +00005382
5383namespace {
5384 /// \brief A set of selectors, which is used to avoid introducing multiple
5385 /// completions with the same selector into the result set.
5386 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5387}
5388
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005389/// \brief Add all of the Objective-C methods in the given Objective-C
5390/// container to the set of results.
5391///
5392/// The container will be a class, protocol, category, or implementation of
5393/// any of the above. This mether will recurse to include methods from
5394/// the superclasses of classes along with their categories, protocols, and
5395/// implementations.
5396///
5397/// \param Container the container in which we'll look to find methods.
5398///
James Dennett596e4752012-06-14 03:11:41 +00005399/// \param WantInstanceMethods Whether to add instance methods (only); if
5400/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005401///
5402/// \param CurContext the context in which we're performing the lookup that
5403/// finds methods.
5404///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005405/// \param AllowSameLength Whether we allow a method to be added to the list
5406/// when it has the same number of parameters as we have selector identifiers.
5407///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005408/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005409static void AddObjCMethods(ObjCContainerDecl *Container,
5410 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005411 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005412 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005413 VisitedSelectorSet &Selectors, bool AllowSameLength,
5414 ResultBuilder &Results, bool InOriginalClass = true,
5415 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005416 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005417 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005418 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005419 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005420 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005421 // The instance methods on the root class can be messaged via the
5422 // metaclass.
5423 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005424 (IsRootClass && !WantInstanceMethods)) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00005425 // Check whether the selector identifiers we've been given are a
5426 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005427 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005428 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005429
David Blaikie82e95a32014-11-19 07:49:47 +00005430 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005431 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005432
5433 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005434 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005435 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005436 if (!InOriginalClass)
5437 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005438 Results.MaybeAddResult(R, CurContext);
5439 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005440 }
5441
Douglas Gregorf37c9492010-09-16 15:34:59 +00005442 // Visit the protocols of protocols.
5443 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005444 if (Protocol->hasDefinition()) {
5445 const ObjCList<ObjCProtocolDecl> &Protocols
5446 = Protocol->getReferencedProtocols();
5447 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5448 E = Protocols.end();
5449 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005450 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5451 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005452 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005453 }
5454
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005455 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005456 return;
5457
5458 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005459 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005460 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5461 Selectors, AllowSameLength, Results, false, IsRootClass);
5462
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005463 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005464 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005465 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005466 CurContext, Selectors, AllowSameLength, Results,
5467 InOriginalClass, IsRootClass);
5468
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005469 // Add a categories protocol methods.
5470 const ObjCList<ObjCProtocolDecl> &Protocols
5471 = CatDecl->getReferencedProtocols();
5472 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5473 E = Protocols.end();
5474 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005475 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5476 Selectors, AllowSameLength, Results, false, IsRootClass);
5477
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005478 // Add methods in category implementations.
5479 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005480 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5481 Selectors, AllowSameLength, Results, InOriginalClass,
5482 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005483 }
5484
5485 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005486 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005487 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005488 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5489 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5490 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005491
5492 // Add methods in our implementation, if any.
5493 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005494 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5495 Selectors, AllowSameLength, Results, InOriginalClass,
5496 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005497}
5498
5499
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005500void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005501 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005502 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005503 if (!Class) {
5504 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005505 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005506 Class = Category->getClassInterface();
5507
5508 if (!Class)
5509 return;
5510 }
5511
5512 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005513 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005514 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005515 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005516 Results.EnterNewScope();
5517
Douglas Gregor1154e272010-09-16 16:06:31 +00005518 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005519 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005520 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005521 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005522 HandleCodeCompleteResults(this, CodeCompleter,
5523 CodeCompletionContext::CCC_Other,
5524 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005525}
5526
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005527void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005528 // Try to find the interface where setters might live.
5529 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005530 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005531 if (!Class) {
5532 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005533 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005534 Class = Category->getClassInterface();
5535
5536 if (!Class)
5537 return;
5538 }
5539
5540 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005541 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005542 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005543 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005544 Results.EnterNewScope();
5545
Douglas Gregor1154e272010-09-16 16:06:31 +00005546 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005547 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005548 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005549
5550 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005551 HandleCodeCompleteResults(this, CodeCompleter,
5552 CodeCompletionContext::CCC_Other,
5553 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005554}
5555
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005556void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5557 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005558 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005559 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005560 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005561 Results.EnterNewScope();
5562
5563 // Add context-sensitive, Objective-C parameter-passing keywords.
5564 bool AddedInOut = false;
5565 if ((DS.getObjCDeclQualifier() &
5566 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5567 Results.AddResult("in");
5568 Results.AddResult("inout");
5569 AddedInOut = true;
5570 }
5571 if ((DS.getObjCDeclQualifier() &
5572 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5573 Results.AddResult("out");
5574 if (!AddedInOut)
5575 Results.AddResult("inout");
5576 }
5577 if ((DS.getObjCDeclQualifier() &
5578 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5579 ObjCDeclSpec::DQ_Oneway)) == 0) {
5580 Results.AddResult("bycopy");
5581 Results.AddResult("byref");
5582 Results.AddResult("oneway");
5583 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005584 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5585 Results.AddResult("nonnull");
5586 Results.AddResult("nullable");
5587 Results.AddResult("null_unspecified");
5588 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00005589
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005590 // If we're completing the return type of an Objective-C method and the
5591 // identifier IBAction refers to a macro, provide a completion item for
5592 // an action, e.g.,
5593 // IBAction)<#selector#>:(id)sender
5594 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005595 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005596 CodeCompletionBuilder Builder(Results.getAllocator(),
5597 Results.getCodeCompletionTUInfo(),
5598 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005599 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005600 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005601 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005602 Builder.AddChunk(CodeCompletionString::CK_Colon);
5603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005604 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005606 Builder.AddTextChunk("sender");
5607 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5608 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005609
5610 // If we're completing the return type, provide 'instancetype'.
5611 if (!IsParameter) {
5612 Results.AddResult(CodeCompletionResult("instancetype"));
5613 }
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005614
Douglas Gregor99fa2642010-08-24 01:06:58 +00005615 // Add various builtin type names and specifiers.
5616 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5617 Results.ExitScope();
5618
5619 // Add the various type names
5620 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5621 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5622 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5623 CodeCompleter->includeGlobals());
5624
5625 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005626 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005627
5628 HandleCodeCompleteResults(this, CodeCompleter,
5629 CodeCompletionContext::CCC_Type,
5630 Results.data(), Results.size());
5631}
5632
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005633/// \brief When we have an expression with type "id", we may assume
5634/// that it has some more-specific class type based on knowledge of
5635/// common uses of Objective-C. This routine returns that class type,
5636/// or NULL if no better result could be determined.
5637static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005638 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005639 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005640 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005641
5642 Selector Sel = Msg->getSelector();
5643 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005644 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005645
5646 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5647 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005648 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005649
5650 ObjCMethodDecl *Method = Msg->getMethodDecl();
5651 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005652 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005653
5654 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005655 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005656 switch (Msg->getReceiverKind()) {
5657 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005658 if (const ObjCObjectType *ObjType
5659 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5660 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005661 break;
5662
5663 case ObjCMessageExpr::Instance: {
5664 QualType T = Msg->getInstanceReceiver()->getType();
5665 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5666 IFace = Ptr->getInterfaceDecl();
5667 break;
5668 }
5669
5670 case ObjCMessageExpr::SuperInstance:
5671 case ObjCMessageExpr::SuperClass:
5672 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005673 }
5674
5675 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005676 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005677
5678 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5679 if (Method->isInstanceMethod())
5680 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5681 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005682 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005683 .Case("autorelease", IFace)
5684 .Case("copy", IFace)
5685 .Case("copyWithZone", IFace)
5686 .Case("mutableCopy", IFace)
5687 .Case("mutableCopyWithZone", IFace)
5688 .Case("awakeFromCoder", IFace)
5689 .Case("replacementObjectFromCoder", IFace)
5690 .Case("class", IFace)
5691 .Case("classForCoder", IFace)
5692 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005693 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005694
5695 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5696 .Case("new", IFace)
5697 .Case("alloc", IFace)
5698 .Case("allocWithZone", IFace)
5699 .Case("class", IFace)
5700 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005701 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005702}
5703
Douglas Gregor6fc04132010-08-27 15:10:57 +00005704// Add a special completion for a message send to "super", which fills in the
5705// most likely case of forwarding all of our arguments to the superclass
5706// function.
5707///
5708/// \param S The semantic analysis object.
5709///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005710/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005711/// the "super" keyword. Otherwise, we just need to provide the arguments.
5712///
5713/// \param SelIdents The identifiers in the selector that have already been
5714/// provided as arguments for a send to "super".
5715///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005716/// \param Results The set of results to augment.
5717///
5718/// \returns the Objective-C method declaration that would be invoked by
5719/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005720static ObjCMethodDecl *AddSuperSendCompletion(
5721 Sema &S, bool NeedSuperKeyword,
5722 ArrayRef<IdentifierInfo *> SelIdents,
5723 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005724 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5725 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005726 return nullptr;
5727
Douglas Gregor6fc04132010-08-27 15:10:57 +00005728 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5729 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005730 return nullptr;
5731
Douglas Gregor6fc04132010-08-27 15:10:57 +00005732 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005733 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005734 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5735 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005736 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5737 CurMethod->isInstanceMethod());
5738
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005739 // Check in categories or class extensions.
5740 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005741 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005742 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005743 CurMethod->isInstanceMethod())))
5744 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005745 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005746 }
5747 }
5748
Douglas Gregor6fc04132010-08-27 15:10:57 +00005749 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005750 return nullptr;
5751
Douglas Gregor6fc04132010-08-27 15:10:57 +00005752 // Check whether the superclass method has the same signature.
5753 if (CurMethod->param_size() != SuperMethod->param_size() ||
5754 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005755 return nullptr;
5756
Douglas Gregor6fc04132010-08-27 15:10:57 +00005757 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5758 CurPEnd = CurMethod->param_end(),
5759 SuperP = SuperMethod->param_begin();
5760 CurP != CurPEnd; ++CurP, ++SuperP) {
5761 // Make sure the parameter types are compatible.
5762 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5763 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005764 return nullptr;
5765
Douglas Gregor6fc04132010-08-27 15:10:57 +00005766 // Make sure we have a parameter name to forward!
5767 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005768 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005769 }
5770
5771 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005772 CodeCompletionBuilder Builder(Results.getAllocator(),
5773 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005774
5775 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005776 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5777 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005778 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005779
5780 // If we need the "super" keyword, add it (plus some spacing).
5781 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005782 Builder.AddTypedTextChunk("super");
5783 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005784 }
5785
5786 Selector Sel = CurMethod->getSelector();
5787 if (Sel.isUnarySelector()) {
5788 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005789 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005790 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005791 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005792 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005793 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005794 } else {
5795 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5796 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005797 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005798 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005799
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005800 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005801 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005802 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005803 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005804 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005805 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005806 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005807 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005808 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005809 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005810 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005811 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005812 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005813 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005814 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005815 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005816 }
5817 }
5818 }
5819
Douglas Gregor78254c82012-03-27 23:34:16 +00005820 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5821 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005822 return SuperMethod;
5823}
5824
Douglas Gregora817a192010-05-27 23:06:34 +00005825void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005826 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005827 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005828 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005829 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005830 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005831 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5832 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005833
Douglas Gregora817a192010-05-27 23:06:34 +00005834 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5835 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005836 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5837 CodeCompleter->includeGlobals());
Douglas Gregora817a192010-05-27 23:06:34 +00005838
5839 // If we are in an Objective-C method inside a class that has a superclass,
5840 // add "super" as an option.
5841 if (ObjCMethodDecl *Method = getCurMethodDecl())
5842 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005843 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005844 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005845
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005846 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005847 }
Douglas Gregora817a192010-05-27 23:06:34 +00005848
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005849 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005850 addThisCompletion(*this, Results);
5851
Douglas Gregora817a192010-05-27 23:06:34 +00005852 Results.ExitScope();
5853
5854 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005855 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005856 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005857 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005858
5859}
5860
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005861void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005862 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005863 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005864 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005865 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5866 // Figure out which interface we're in.
5867 CDecl = CurMethod->getClassInterface();
5868 if (!CDecl)
5869 return;
5870
5871 // Find the superclass of this class.
5872 CDecl = CDecl->getSuperClass();
5873 if (!CDecl)
5874 return;
5875
5876 if (CurMethod->isInstanceMethod()) {
5877 // We are inside an instance method, which means that the message
5878 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005879 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005880 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005881 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005882 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005883 }
5884
5885 // Fall through to send to the superclass in CDecl.
5886 } else {
5887 // "super" may be the name of a type or variable. Figure out which
5888 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005889 IdentifierInfo *Super = getSuperIdentifier();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005890 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5891 LookupOrdinaryName);
5892 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5893 // "super" names an interface. Use it.
5894 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005895 if (const ObjCObjectType *Iface
5896 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5897 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005898 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5899 // "super" names an unresolved type; we can't be more specific.
5900 } else {
5901 // Assume that "super" names some kind of value and parse that way.
5902 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005903 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005904 UnqualifiedId id;
5905 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005906 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5907 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005908 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005909 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005910 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005911 }
5912
5913 // Fall through
5914 }
5915
John McCallba7bf592010-08-24 05:47:05 +00005916 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005917 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005918 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005919 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005920 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005921 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005922}
5923
Douglas Gregor74661272010-09-21 00:03:25 +00005924/// \brief Given a set of code-completion results for the argument of a message
5925/// send, determine the preferred type (if any) for that argument expression.
5926static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5927 unsigned NumSelIdents) {
5928 typedef CodeCompletionResult Result;
5929 ASTContext &Context = Results.getSema().Context;
5930
5931 QualType PreferredType;
5932 unsigned BestPriority = CCP_Unlikely * 2;
5933 Result *ResultsData = Results.data();
5934 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5935 Result &R = ResultsData[I];
5936 if (R.Kind == Result::RK_Declaration &&
5937 isa<ObjCMethodDecl>(R.Declaration)) {
5938 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00005939 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00005940 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00005941 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00005942 ->getType();
5943 if (R.Priority < BestPriority || PreferredType.isNull()) {
5944 BestPriority = R.Priority;
5945 PreferredType = MyPreferredType;
5946 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5947 MyPreferredType)) {
5948 PreferredType = QualType();
5949 }
5950 }
5951 }
5952 }
5953 }
5954
5955 return PreferredType;
5956}
5957
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005958static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5959 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005960 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005961 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005962 bool IsSuper,
5963 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005964 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00005965 ObjCInterfaceDecl *CDecl = nullptr;
5966
Douglas Gregor8ce33212009-11-17 17:59:40 +00005967 // If the given name refers to an interface type, retrieve the
5968 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005969 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005970 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005971 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00005972 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5973 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00005974 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005975
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005976 // Add all of the factory methods in this Objective-C class, its protocols,
5977 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00005978 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005979
Douglas Gregor6fc04132010-08-27 15:10:57 +00005980 // If this is a send-to-super, try to add the special "super" send
5981 // completion.
5982 if (IsSuper) {
5983 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005984 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00005985 Results.Ignore(SuperMethod);
5986 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005987
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005988 // If we're inside an Objective-C method definition, prefer its selector to
5989 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005990 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005991 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005992
Douglas Gregor1154e272010-09-16 16:06:31 +00005993 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00005994 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005995 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005996 SemaRef.CurContext, Selectors, AtArgumentExpression,
5997 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005998 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00005999 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006000
Douglas Gregord720daf2010-04-06 17:30:22 +00006001 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006002 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006003 if (SemaRef.getExternalSource()) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006004 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006005 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006006 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006007 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006008 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006009 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006010
6011 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006012 }
6013 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006014
6015 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6016 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006017 M != MEnd; ++M) {
6018 for (ObjCMethodList *MethList = &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006019 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006020 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006021 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006022 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006023
Nico Weber2e0c8f72014-12-27 03:58:08 +00006024 Result R(MethList->getMethod(),
6025 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006026 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006027 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006028 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006029 }
6030 }
6031 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006032
6033 Results.ExitScope();
6034}
Douglas Gregor6285f752010-04-06 16:40:00 +00006035
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006036void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006037 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006038 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006039 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00006040
6041 QualType T = this->GetTypeFromParser(Receiver);
6042
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006043 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006044 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006045 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006046 T, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006047
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006048 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006049 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00006050
6051 // If we're actually at the argument expression (rather than prior to the
6052 // selector), we're actually performing code completion for an expression.
6053 // Determine whether we have a single, best method. If so, we can
6054 // code-complete the expression using the corresponding parameter type as
6055 // our preferred type, improving completion results.
6056 if (AtArgumentExpression) {
6057 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006058 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006059 if (PreferredType.isNull())
6060 CodeCompleteOrdinaryName(S, PCC_Expression);
6061 else
6062 CodeCompleteExpression(S, PreferredType);
6063 return;
6064 }
6065
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006066 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006067 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006068 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006069}
6070
Richard Trieu2bd04012011-09-09 02:00:50 +00006071void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006072 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006073 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006074 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006075 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00006076
6077 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00006078
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006079 // If necessary, apply function/array conversion to the receiver.
6080 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006081 if (RecExpr) {
6082 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6083 if (Conv.isInvalid()) // conversion failed. bail.
6084 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006085 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006086 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00006087 QualType ReceiverType = RecExpr? RecExpr->getType()
6088 : Super? Context.getObjCObjectPointerType(
6089 Context.getObjCInterfaceType(Super))
6090 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00006091
Douglas Gregordc520b02010-11-08 21:12:30 +00006092 // If we're messaging an expression with type "id" or "Class", check
6093 // whether we know something special about the receiver that allows
6094 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006095 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006096 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6097 if (ReceiverType->isObjCClassType())
6098 return CodeCompleteObjCClassMessage(S,
6099 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006100 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006101 AtArgumentExpression, Super);
6102
6103 ReceiverType = Context.getObjCObjectPointerType(
6104 Context.getObjCInterfaceType(IFace));
6105 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006106 } else if (RecExpr && getLangOpts().CPlusPlus) {
6107 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6108 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006109 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006110 ReceiverType = RecExpr->getType();
6111 }
6112 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006113
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006114 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006115 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006116 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006117 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006118 ReceiverType, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006119
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006120 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006121
Douglas Gregor6fc04132010-08-27 15:10:57 +00006122 // If this is a send-to-super, try to add the special "super" send
6123 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006124 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006125 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006126 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006127 Results.Ignore(SuperMethod);
6128 }
6129
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006130 // If we're inside an Objective-C method definition, prefer its selector to
6131 // others.
6132 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6133 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006134
Douglas Gregor1154e272010-09-16 16:06:31 +00006135 // Keep track of the selectors we've already added.
6136 VisitedSelectorSet Selectors;
6137
Douglas Gregora3329fa2009-11-18 00:06:18 +00006138 // Handle messages to Class. This really isn't a message to an instance
6139 // method, so we treat it the same way we would treat a message send to a
6140 // class method.
6141 if (ReceiverType->isObjCClassType() ||
6142 ReceiverType->isObjCQualifiedClassType()) {
6143 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6144 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006145 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006146 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006147 }
6148 }
6149 // Handle messages to a qualified ID ("id<foo>").
6150 else if (const ObjCObjectPointerType *QualID
6151 = ReceiverType->getAsObjCQualifiedIdType()) {
6152 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006153 for (auto *I : QualID->quals())
6154 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006155 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006156 }
6157 // Handle messages to a pointer to interface type.
6158 else if (const ObjCObjectPointerType *IFacePtr
6159 = ReceiverType->getAsObjCInterfacePointerType()) {
6160 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006161 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006162 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006163 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006164
6165 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006166 for (auto *I : IFacePtr->quals())
6167 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006168 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006169 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006170 // Handle messages to "id".
6171 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006172 // We're messaging "id", so provide all instance methods we know
6173 // about as code-completion results.
6174
6175 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006176 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006177 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006178 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6179 I != N; ++I) {
6180 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006181 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006182 continue;
6183
Sebastian Redl75d8a322010-08-02 23:18:59 +00006184 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006185 }
6186 }
6187
Sebastian Redl75d8a322010-08-02 23:18:59 +00006188 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6189 MEnd = MethodPool.end();
6190 M != MEnd; ++M) {
6191 for (ObjCMethodList *MethList = &M->second.first;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006192 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006193 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006194 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006195 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00006196
Nico Weber2e0c8f72014-12-27 03:58:08 +00006197 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006198 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006199
Nico Weber2e0c8f72014-12-27 03:58:08 +00006200 Result R(MethList->getMethod(),
6201 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006202 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006203 R.AllParametersAreInformative = false;
6204 Results.MaybeAddResult(R, CurContext);
6205 }
6206 }
6207 }
Steve Naroffeae65032009-11-07 02:08:14 +00006208 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00006209
6210
6211 // If we're actually at the argument expression (rather than prior to the
6212 // selector), we're actually performing code completion for an expression.
6213 // Determine whether we have a single, best method. If so, we can
6214 // code-complete the expression using the corresponding parameter type as
6215 // our preferred type, improving completion results.
6216 if (AtArgumentExpression) {
6217 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006218 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006219 if (PreferredType.isNull())
6220 CodeCompleteOrdinaryName(S, PCC_Expression);
6221 else
6222 CodeCompleteExpression(S, PreferredType);
6223 return;
6224 }
6225
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006226 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006227 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006228 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006229}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006230
Douglas Gregor68762e72010-08-23 21:17:50 +00006231void Sema::CodeCompleteObjCForCollection(Scope *S,
6232 DeclGroupPtrTy IterationVar) {
6233 CodeCompleteExpressionData Data;
6234 Data.ObjCCollection = true;
6235
6236 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006237 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006238 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6239 if (*I)
6240 Data.IgnoreDecls.push_back(*I);
6241 }
6242 }
6243
6244 CodeCompleteExpression(S, Data);
6245}
6246
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006247void Sema::CodeCompleteObjCSelector(Scope *S,
6248 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006249 // If we have an external source, load the entire class method
6250 // pool from the AST file.
6251 if (ExternalSource) {
6252 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6253 I != N; ++I) {
6254 Selector Sel = ExternalSource->GetExternalSelector(I);
6255 if (Sel.isNull() || MethodPool.count(Sel))
6256 continue;
6257
6258 ReadMethodPool(Sel);
6259 }
6260 }
6261
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006262 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006263 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006264 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006265 Results.EnterNewScope();
6266 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6267 MEnd = MethodPool.end();
6268 M != MEnd; ++M) {
6269
6270 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006271 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006272 continue;
6273
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006274 CodeCompletionBuilder Builder(Results.getAllocator(),
6275 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006276 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006277 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006278 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006279 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006280 continue;
6281 }
6282
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006283 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006284 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006285 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006286 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006287 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006288 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006289 Accumulator.clear();
6290 }
6291 }
6292
Benjamin Kramer632500c2011-07-26 16:59:25 +00006293 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006294 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006295 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006296 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006297 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006298 }
6299 Results.ExitScope();
6300
6301 HandleCodeCompleteResults(this, CodeCompleter,
6302 CodeCompletionContext::CCC_SelectorName,
6303 Results.data(), Results.size());
6304}
6305
Douglas Gregorbaf69612009-11-18 04:19:12 +00006306/// \brief Add all of the protocol declarations that we find in the given
6307/// (translation unit) context.
6308static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006309 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006310 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006311 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00006312
Aaron Ballman629afae2014-03-07 19:56:05 +00006313 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006314 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006315 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006316 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006317 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6318 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006319 }
6320}
6321
Craig Topper883dd332015-12-24 23:58:11 +00006322void Sema::CodeCompleteObjCProtocolReferences(
6323 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006324 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006325 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006326 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006327
Chandler Carruthede11632016-11-04 06:06:50 +00006328 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006329 Results.EnterNewScope();
6330
6331 // Tell the result set to ignore all of the protocols we have
6332 // already seen.
6333 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006334 for (const IdentifierLocPair &Pair : Protocols)
6335 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6336 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006337 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006338
Douglas Gregora3b23b02010-12-09 21:44:02 +00006339 // Add all protocols.
6340 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6341 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006342
Douglas Gregora3b23b02010-12-09 21:44:02 +00006343 Results.ExitScope();
6344 }
6345
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006346 HandleCodeCompleteResults(this, CodeCompleter,
6347 CodeCompletionContext::CCC_ObjCProtocolName,
6348 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006349}
6350
6351void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006352 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006353 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006354 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006355
Chandler Carruthede11632016-11-04 06:06:50 +00006356 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006357 Results.EnterNewScope();
6358
6359 // Add all protocols.
6360 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6361 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006362
Douglas Gregora3b23b02010-12-09 21:44:02 +00006363 Results.ExitScope();
6364 }
6365
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006366 HandleCodeCompleteResults(this, CodeCompleter,
6367 CodeCompletionContext::CCC_ObjCProtocolName,
6368 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006369}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006370
6371/// \brief Add all of the Objective-C interface declarations that we find in
6372/// the given (translation unit) context.
6373static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6374 bool OnlyForwardDeclarations,
6375 bool OnlyUnimplemented,
6376 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006377 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00006378
Aaron Ballman629afae2014-03-07 19:56:05 +00006379 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006380 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006381 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006382 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006383 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006384 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6385 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006386 }
6387}
6388
6389void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006390 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006391 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006392 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006393 Results.EnterNewScope();
6394
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006395 if (CodeCompleter->includeGlobals()) {
6396 // Add all classes.
6397 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6398 false, Results);
6399 }
6400
Douglas Gregor49c22a72009-11-18 16:26:39 +00006401 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006402
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006403 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006404 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006405 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006406}
6407
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006408void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
6409 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006410 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006411 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006412 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006413 Results.EnterNewScope();
6414
6415 // Make sure that we ignore the class we're currently defining.
6416 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006417 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006418 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006419 Results.Ignore(CurClass);
6420
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006421 if (CodeCompleter->includeGlobals()) {
6422 // Add all classes.
6423 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6424 false, Results);
6425 }
6426
Douglas Gregor49c22a72009-11-18 16:26:39 +00006427 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006428
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006429 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006430 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006431 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006432}
6433
6434void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006435 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006436 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006437 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006438 Results.EnterNewScope();
6439
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006440 if (CodeCompleter->includeGlobals()) {
6441 // Add all unimplemented classes.
6442 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6443 true, Results);
6444 }
6445
Douglas Gregor49c22a72009-11-18 16:26:39 +00006446 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006447
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006448 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006449 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006450 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006451}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006452
6453void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006454 IdentifierInfo *ClassName,
6455 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006456 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006457
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006458 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006459 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006460 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006461
6462 // Ignore any categories we find that have already been implemented by this
6463 // interface.
6464 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6465 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006466 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006467 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006468 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006469 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006470 }
6471
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006472 // Add all of the categories we know about.
6473 Results.EnterNewScope();
6474 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Aaron Ballman629afae2014-03-07 19:56:05 +00006475 for (const auto *D : TU->decls())
6476 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006477 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006478 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6479 nullptr),
6480 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006481 Results.ExitScope();
6482
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006483 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006484 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006485 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006486}
6487
6488void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006489 IdentifierInfo *ClassName,
6490 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006491 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006492
6493 // Find the corresponding interface. If we couldn't find the interface, the
6494 // program itself is ill-formed. However, we'll try to be helpful still by
6495 // providing the list of all of the categories we know about.
6496 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006497 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006498 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6499 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006500 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006501
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006502 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006503 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006504 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006505
6506 // Add all of the categories that have have corresponding interface
6507 // declarations in this class and any of its superclasses, except for
6508 // already-implemented categories in the class itself.
6509 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6510 Results.EnterNewScope();
6511 bool IgnoreImplemented = true;
6512 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006513 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006514 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006515 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006516 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6517 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006518 }
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006519
6520 Class = Class->getSuperClass();
6521 IgnoreImplemented = false;
6522 }
6523 Results.ExitScope();
6524
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006525 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006526 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006527 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006528}
Douglas Gregor5d649882009-11-18 22:32:06 +00006529
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006530void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006531 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006532 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006533 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006534 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006535
6536 // Figure out where this @synthesize lives.
6537 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006538 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006539 if (!Container ||
6540 (!isa<ObjCImplementationDecl>(Container) &&
6541 !isa<ObjCCategoryImplDecl>(Container)))
6542 return;
6543
6544 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006545 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006546 for (const auto *D : Container->decls())
6547 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006548 Results.Ignore(PropertyImpl->getPropertyDecl());
6549
6550 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006551 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006552 Results.EnterNewScope();
6553 if (ObjCImplementationDecl *ClassImpl
6554 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006555 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Douglas Gregor95147142011-05-05 15:50:42 +00006556 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006557 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006558 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006559 AddObjCProperties(CCContext,
6560 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00006561 false, /*AllowNullaryMethods=*/false, CurContext,
6562 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006563 Results.ExitScope();
6564
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006565 HandleCodeCompleteResults(this, CodeCompleter,
6566 CodeCompletionContext::CCC_Other,
6567 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006568}
6569
6570void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006571 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006572 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006573 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006574 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006575 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006576
6577 // Figure out where this @synthesize lives.
6578 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006579 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006580 if (!Container ||
6581 (!isa<ObjCImplementationDecl>(Container) &&
6582 !isa<ObjCCategoryImplDecl>(Container)))
6583 return;
6584
6585 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006586 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006587 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006588 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006589 Class = ClassImpl->getClassInterface();
6590 else
6591 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6592 ->getClassInterface();
6593
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006594 // Determine the type of the property we're synthesizing.
6595 QualType PropertyType = Context.getObjCIdType();
6596 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006597 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6598 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006599 PropertyType
6600 = Property->getType().getNonReferenceType().getUnqualifiedType();
6601
6602 // Give preference to ivars
6603 Results.setPreferredType(PropertyType);
6604 }
6605 }
6606
Douglas Gregor5d649882009-11-18 22:32:06 +00006607 // Add all of the instance variables in this class and its superclasses.
6608 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006609 bool SawSimilarlyNamedIvar = false;
6610 std::string NameWithPrefix;
6611 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006612 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006613 std::string NameWithSuffix = PropertyName->getName().str();
6614 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006615 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006616 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6617 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006618 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6619 CurContext, nullptr, false);
6620
Douglas Gregor331faa02011-04-18 14:13:53 +00006621 // Determine whether we've seen an ivar with a name similar to the
6622 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006623 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006624 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006625 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006626 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006627
6628 // Reduce the priority of this result by one, to give it a slight
6629 // advantage over other results whose names don't match so closely.
6630 if (Results.size() &&
6631 Results.data()[Results.size() - 1].Kind
6632 == CodeCompletionResult::RK_Declaration &&
6633 Results.data()[Results.size() - 1].Declaration == Ivar)
6634 Results.data()[Results.size() - 1].Priority--;
6635 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006636 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006637 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006638
6639 if (!SawSimilarlyNamedIvar) {
6640 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006641 // an ivar of the appropriate type.
6642 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006643 typedef CodeCompletionResult Result;
6644 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006645 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6646 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006647
Douglas Gregor75acd922011-09-27 23:30:47 +00006648 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006649 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006650 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006651 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6652 Results.AddResult(Result(Builder.TakeString(), Priority,
6653 CXCursor_ObjCIvarDecl));
6654 }
6655
Douglas Gregor5d649882009-11-18 22:32:06 +00006656 Results.ExitScope();
6657
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006658 HandleCodeCompleteResults(this, CodeCompleter,
6659 CodeCompletionContext::CCC_Other,
6660 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006661}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006662
Douglas Gregor416b5752010-08-25 01:08:01 +00006663// Mapping from selectors to the methods that implement that selector, along
6664// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006665typedef llvm::DenseMap<
6666 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006667
6668/// \brief Find all of the methods that reside in the given container
6669/// (and its superclasses, protocols, etc.) that meet the given
6670/// criteria. Insert those methods into the map of known methods,
6671/// indexed by selector so they can be easily found.
6672static void FindImplementableMethods(ASTContext &Context,
6673 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006674 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006675 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006676 KnownMethodsMap &KnownMethods,
6677 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006678 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006679 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006680 if (!IFace->hasDefinition())
6681 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006682
6683 IFace = IFace->getDefinition();
6684 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006685
Douglas Gregor636a61e2010-04-07 00:21:17 +00006686 const ObjCList<ObjCProtocolDecl> &Protocols
6687 = IFace->getReferencedProtocols();
6688 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006689 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006690 I != E; ++I)
6691 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006692 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006693
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006694 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006695 for (auto *Cat : IFace->visible_categories()) {
6696 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006697 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006698 }
6699
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006700 // Visit the superclass.
6701 if (IFace->getSuperClass())
6702 FindImplementableMethods(Context, IFace->getSuperClass(),
6703 WantInstanceMethods, ReturnType,
6704 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006705 }
6706
6707 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6708 // Recurse into protocols.
6709 const ObjCList<ObjCProtocolDecl> &Protocols
6710 = Category->getReferencedProtocols();
6711 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006712 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006713 I != E; ++I)
6714 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006715 KnownMethods, InOriginalClass);
6716
6717 // If this category is the original class, jump to the interface.
6718 if (InOriginalClass && Category->getClassInterface())
6719 FindImplementableMethods(Context, Category->getClassInterface(),
6720 WantInstanceMethods, ReturnType, KnownMethods,
6721 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006722 }
6723
6724 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006725 // Make sure we have a definition; that's what we'll walk.
6726 if (!Protocol->hasDefinition())
6727 return;
6728 Protocol = Protocol->getDefinition();
6729 Container = Protocol;
6730
6731 // Recurse into protocols.
6732 const ObjCList<ObjCProtocolDecl> &Protocols
6733 = Protocol->getReferencedProtocols();
6734 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6735 E = Protocols.end();
6736 I != E; ++I)
6737 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6738 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006739 }
6740
6741 // Add methods in this container. This operation occurs last because
6742 // we want the methods from this container to override any methods
6743 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006744 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006745 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006746 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006747 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006748 continue;
6749
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006750 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006751 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006752 }
6753 }
6754}
6755
Douglas Gregor669a25a2011-02-17 00:22:45 +00006756/// \brief Add the parenthesized return or parameter type chunk to a code
6757/// completion string.
6758static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006759 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006760 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006761 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006762 CodeCompletionBuilder &Builder) {
6763 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006764 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006765 if (!Quals.empty())
6766 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006767 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006768 Builder.getAllocator()));
6769 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6770}
6771
6772/// \brief Determine whether the given class is or inherits from a class by
6773/// the given name.
6774static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006775 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006776 if (!Class)
6777 return false;
6778
6779 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6780 return true;
6781
6782 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6783}
6784
6785/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6786/// Key-Value Observing (KVO).
6787static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6788 bool IsInstanceMethod,
6789 QualType ReturnType,
6790 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006791 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006792 ResultBuilder &Results) {
6793 IdentifierInfo *PropName = Property->getIdentifier();
6794 if (!PropName || PropName->getLength() == 0)
6795 return;
6796
Douglas Gregor75acd922011-09-27 23:30:47 +00006797 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6798
Douglas Gregor669a25a2011-02-17 00:22:45 +00006799 // Builder that will create each code completion.
6800 typedef CodeCompletionResult Result;
6801 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006802 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006803
6804 // The selector table.
6805 SelectorTable &Selectors = Context.Selectors;
6806
6807 // The property name, copied into the code completion allocation region
6808 // on demand.
6809 struct KeyHolder {
6810 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006811 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006812 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006813
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006814 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006815 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6816
Douglas Gregor669a25a2011-02-17 00:22:45 +00006817 operator const char *() {
6818 if (CopiedKey)
6819 return CopiedKey;
6820
6821 return CopiedKey = Allocator.CopyString(Key);
6822 }
6823 } Key(Allocator, PropName->getName());
6824
6825 // The uppercased name of the property name.
6826 std::string UpperKey = PropName->getName();
6827 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006828 UpperKey[0] = toUppercase(UpperKey[0]);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006829
6830 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6831 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6832 Property->getType());
6833 bool ReturnTypeMatchesVoid
6834 = ReturnType.isNull() || ReturnType->isVoidType();
6835
6836 // Add the normal accessor -(type)key.
6837 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006838 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006839 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6840 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006841 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6842 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006843
6844 Builder.AddTypedTextChunk(Key);
6845 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6846 CXCursor_ObjCInstanceMethodDecl));
6847 }
6848
6849 // If we have an integral or boolean property (or the user has provided
6850 // an integral or boolean return type), add the accessor -(type)isKey.
6851 if (IsInstanceMethod &&
6852 ((!ReturnType.isNull() &&
6853 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6854 (ReturnType.isNull() &&
6855 (Property->getType()->isIntegerType() ||
6856 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006857 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006858 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006859 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6860 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006861 if (ReturnType.isNull()) {
6862 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6863 Builder.AddTextChunk("BOOL");
6864 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6865 }
6866
6867 Builder.AddTypedTextChunk(
6868 Allocator.CopyString(SelectorId->getName()));
6869 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6870 CXCursor_ObjCInstanceMethodDecl));
6871 }
6872 }
6873
6874 // Add the normal mutator.
6875 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6876 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006877 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006878 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006879 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006880 if (ReturnType.isNull()) {
6881 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6882 Builder.AddTextChunk("void");
6883 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6884 }
6885
6886 Builder.AddTypedTextChunk(
6887 Allocator.CopyString(SelectorId->getName()));
6888 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006889 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6890 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006891 Builder.AddTextChunk(Key);
6892 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6893 CXCursor_ObjCInstanceMethodDecl));
6894 }
6895 }
6896
6897 // Indexed and unordered accessors
6898 unsigned IndexedGetterPriority = CCP_CodePattern;
6899 unsigned IndexedSetterPriority = CCP_CodePattern;
6900 unsigned UnorderedGetterPriority = CCP_CodePattern;
6901 unsigned UnorderedSetterPriority = CCP_CodePattern;
6902 if (const ObjCObjectPointerType *ObjCPointer
6903 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6904 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6905 // If this interface type is not provably derived from a known
6906 // collection, penalize the corresponding completions.
6907 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6908 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6909 if (!InheritsFromClassNamed(IFace, "NSArray"))
6910 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6911 }
6912
6913 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6914 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6915 if (!InheritsFromClassNamed(IFace, "NSSet"))
6916 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6917 }
6918 }
6919 } else {
6920 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6921 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6922 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6923 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6924 }
6925
6926 // Add -(NSUInteger)countOf<key>
6927 if (IsInstanceMethod &&
6928 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006929 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006930 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006931 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6932 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006933 if (ReturnType.isNull()) {
6934 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6935 Builder.AddTextChunk("NSUInteger");
6936 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6937 }
6938
6939 Builder.AddTypedTextChunk(
6940 Allocator.CopyString(SelectorId->getName()));
6941 Results.AddResult(Result(Builder.TakeString(),
6942 std::min(IndexedGetterPriority,
6943 UnorderedGetterPriority),
6944 CXCursor_ObjCInstanceMethodDecl));
6945 }
6946 }
6947
6948 // Indexed getters
6949 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6950 if (IsInstanceMethod &&
6951 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006952 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006953 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006954 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006955 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006956 if (ReturnType.isNull()) {
6957 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6958 Builder.AddTextChunk("id");
6959 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6960 }
6961
6962 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6963 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6964 Builder.AddTextChunk("NSUInteger");
6965 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6966 Builder.AddTextChunk("index");
6967 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6968 CXCursor_ObjCInstanceMethodDecl));
6969 }
6970 }
6971
6972 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6973 if (IsInstanceMethod &&
6974 (ReturnType.isNull() ||
6975 (ReturnType->isObjCObjectPointerType() &&
6976 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6977 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6978 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006979 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006980 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006981 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006982 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006983 if (ReturnType.isNull()) {
6984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6985 Builder.AddTextChunk("NSArray *");
6986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6987 }
6988
6989 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6990 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6991 Builder.AddTextChunk("NSIndexSet *");
6992 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6993 Builder.AddTextChunk("indexes");
6994 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6995 CXCursor_ObjCInstanceMethodDecl));
6996 }
6997 }
6998
6999 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7000 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007001 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007002 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007003 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007004 &Context.Idents.get("range")
7005 };
7006
David Blaikie82e95a32014-11-19 07:49:47 +00007007 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007008 if (ReturnType.isNull()) {
7009 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7010 Builder.AddTextChunk("void");
7011 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7012 }
7013
7014 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7015 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7016 Builder.AddPlaceholderChunk("object-type");
7017 Builder.AddTextChunk(" **");
7018 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7019 Builder.AddTextChunk("buffer");
7020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7021 Builder.AddTypedTextChunk("range:");
7022 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7023 Builder.AddTextChunk("NSRange");
7024 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7025 Builder.AddTextChunk("inRange");
7026 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7027 CXCursor_ObjCInstanceMethodDecl));
7028 }
7029 }
7030
7031 // Mutable indexed accessors
7032
7033 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7034 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007035 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007036 IdentifierInfo *SelectorIds[2] = {
7037 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007038 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007039 };
7040
David Blaikie82e95a32014-11-19 07:49:47 +00007041 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007042 if (ReturnType.isNull()) {
7043 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7044 Builder.AddTextChunk("void");
7045 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7046 }
7047
7048 Builder.AddTypedTextChunk("insertObject:");
7049 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7050 Builder.AddPlaceholderChunk("object-type");
7051 Builder.AddTextChunk(" *");
7052 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7053 Builder.AddTextChunk("object");
7054 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7055 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7056 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7057 Builder.AddPlaceholderChunk("NSUInteger");
7058 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7059 Builder.AddTextChunk("index");
7060 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7061 CXCursor_ObjCInstanceMethodDecl));
7062 }
7063 }
7064
7065 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7066 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007067 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007068 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007069 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007070 &Context.Idents.get("atIndexes")
7071 };
7072
David Blaikie82e95a32014-11-19 07:49:47 +00007073 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007074 if (ReturnType.isNull()) {
7075 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7076 Builder.AddTextChunk("void");
7077 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7078 }
7079
7080 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7081 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7082 Builder.AddTextChunk("NSArray *");
7083 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7084 Builder.AddTextChunk("array");
7085 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7086 Builder.AddTypedTextChunk("atIndexes:");
7087 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7088 Builder.AddPlaceholderChunk("NSIndexSet *");
7089 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7090 Builder.AddTextChunk("indexes");
7091 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7092 CXCursor_ObjCInstanceMethodDecl));
7093 }
7094 }
7095
7096 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7097 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007098 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007099 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007100 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007101 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007102 if (ReturnType.isNull()) {
7103 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7104 Builder.AddTextChunk("void");
7105 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7106 }
7107
7108 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7109 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7110 Builder.AddTextChunk("NSUInteger");
7111 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7112 Builder.AddTextChunk("index");
7113 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7114 CXCursor_ObjCInstanceMethodDecl));
7115 }
7116 }
7117
7118 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7119 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007120 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007121 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007122 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007123 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007124 if (ReturnType.isNull()) {
7125 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7126 Builder.AddTextChunk("void");
7127 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7128 }
7129
7130 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7131 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7132 Builder.AddTextChunk("NSIndexSet *");
7133 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7134 Builder.AddTextChunk("indexes");
7135 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7136 CXCursor_ObjCInstanceMethodDecl));
7137 }
7138 }
7139
7140 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7141 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007142 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007143 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007144 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007145 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007146 &Context.Idents.get("withObject")
7147 };
7148
David Blaikie82e95a32014-11-19 07:49:47 +00007149 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007150 if (ReturnType.isNull()) {
7151 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7152 Builder.AddTextChunk("void");
7153 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7154 }
7155
7156 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7157 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7158 Builder.AddPlaceholderChunk("NSUInteger");
7159 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7160 Builder.AddTextChunk("index");
7161 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7162 Builder.AddTypedTextChunk("withObject:");
7163 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7164 Builder.AddTextChunk("id");
7165 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7166 Builder.AddTextChunk("object");
7167 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7168 CXCursor_ObjCInstanceMethodDecl));
7169 }
7170 }
7171
7172 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7173 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007174 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007175 = (Twine("replace") + UpperKey + "AtIndexes").str();
7176 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007177 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007178 &Context.Idents.get(SelectorName1),
7179 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007180 };
7181
David Blaikie82e95a32014-11-19 07:49:47 +00007182 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007183 if (ReturnType.isNull()) {
7184 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7185 Builder.AddTextChunk("void");
7186 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7187 }
7188
7189 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7190 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7191 Builder.AddPlaceholderChunk("NSIndexSet *");
7192 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7193 Builder.AddTextChunk("indexes");
7194 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7195 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7196 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7197 Builder.AddTextChunk("NSArray *");
7198 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7199 Builder.AddTextChunk("array");
7200 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7201 CXCursor_ObjCInstanceMethodDecl));
7202 }
7203 }
7204
7205 // Unordered getters
7206 // - (NSEnumerator *)enumeratorOfKey
7207 if (IsInstanceMethod &&
7208 (ReturnType.isNull() ||
7209 (ReturnType->isObjCObjectPointerType() &&
7210 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7211 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7212 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007213 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007214 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007215 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7216 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007217 if (ReturnType.isNull()) {
7218 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7219 Builder.AddTextChunk("NSEnumerator *");
7220 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7221 }
7222
7223 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7224 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7225 CXCursor_ObjCInstanceMethodDecl));
7226 }
7227 }
7228
7229 // - (type *)memberOfKey:(type *)object
7230 if (IsInstanceMethod &&
7231 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007232 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007233 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007234 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007235 if (ReturnType.isNull()) {
7236 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7237 Builder.AddPlaceholderChunk("object-type");
7238 Builder.AddTextChunk(" *");
7239 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7240 }
7241
7242 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7243 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7244 if (ReturnType.isNull()) {
7245 Builder.AddPlaceholderChunk("object-type");
7246 Builder.AddTextChunk(" *");
7247 } else {
7248 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007249 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007250 Builder.getAllocator()));
7251 }
7252 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7253 Builder.AddTextChunk("object");
7254 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7255 CXCursor_ObjCInstanceMethodDecl));
7256 }
7257 }
7258
7259 // Mutable unordered accessors
7260 // - (void)addKeyObject:(type *)object
7261 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007262 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007263 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007264 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007265 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007266 if (ReturnType.isNull()) {
7267 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7268 Builder.AddTextChunk("void");
7269 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7270 }
7271
7272 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7273 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7274 Builder.AddPlaceholderChunk("object-type");
7275 Builder.AddTextChunk(" *");
7276 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7277 Builder.AddTextChunk("object");
7278 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7279 CXCursor_ObjCInstanceMethodDecl));
7280 }
7281 }
7282
7283 // - (void)addKey:(NSSet *)objects
7284 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007285 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007286 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007287 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007288 if (ReturnType.isNull()) {
7289 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7290 Builder.AddTextChunk("void");
7291 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7292 }
7293
7294 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7295 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7296 Builder.AddTextChunk("NSSet *");
7297 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7298 Builder.AddTextChunk("objects");
7299 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7300 CXCursor_ObjCInstanceMethodDecl));
7301 }
7302 }
7303
7304 // - (void)removeKeyObject:(type *)object
7305 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007306 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007307 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007308 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007309 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007310 if (ReturnType.isNull()) {
7311 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7312 Builder.AddTextChunk("void");
7313 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7314 }
7315
7316 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7317 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7318 Builder.AddPlaceholderChunk("object-type");
7319 Builder.AddTextChunk(" *");
7320 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7321 Builder.AddTextChunk("object");
7322 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7323 CXCursor_ObjCInstanceMethodDecl));
7324 }
7325 }
7326
7327 // - (void)removeKey:(NSSet *)objects
7328 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007329 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007330 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007331 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007332 if (ReturnType.isNull()) {
7333 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7334 Builder.AddTextChunk("void");
7335 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7336 }
7337
7338 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7339 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7340 Builder.AddTextChunk("NSSet *");
7341 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7342 Builder.AddTextChunk("objects");
7343 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7344 CXCursor_ObjCInstanceMethodDecl));
7345 }
7346 }
7347
7348 // - (void)intersectKey:(NSSet *)objects
7349 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007350 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007351 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007352 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007353 if (ReturnType.isNull()) {
7354 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7355 Builder.AddTextChunk("void");
7356 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7357 }
7358
7359 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7360 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7361 Builder.AddTextChunk("NSSet *");
7362 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7363 Builder.AddTextChunk("objects");
7364 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7365 CXCursor_ObjCInstanceMethodDecl));
7366 }
7367 }
7368
7369 // Key-Value Observing
7370 // + (NSSet *)keyPathsForValuesAffectingKey
7371 if (!IsInstanceMethod &&
7372 (ReturnType.isNull() ||
7373 (ReturnType->isObjCObjectPointerType() &&
7374 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7375 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7376 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007377 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007378 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007379 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007380 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7381 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007382 if (ReturnType.isNull()) {
7383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007384 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007385 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7386 }
7387
7388 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7389 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007390 CXCursor_ObjCClassMethodDecl));
7391 }
7392 }
7393
7394 // + (BOOL)automaticallyNotifiesObserversForKey
7395 if (!IsInstanceMethod &&
7396 (ReturnType.isNull() ||
7397 ReturnType->isIntegerType() ||
7398 ReturnType->isBooleanType())) {
7399 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007400 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007401 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007402 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7403 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007404 if (ReturnType.isNull()) {
7405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7406 Builder.AddTextChunk("BOOL");
7407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7408 }
7409
7410 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7411 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
7412 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007413 }
7414 }
7415}
7416
Alex Lorenzb8740422017-10-24 16:39:37 +00007417void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007418 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007419 // Determine the return type of the method we're declaring, if
7420 // provided.
7421 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007422 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007423 if (CurContext->isObjCContainer()) {
7424 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7425 IDecl = cast<Decl>(OCD);
7426 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007427 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007428 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007429 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007430 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007431 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7432 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007433 IsInImplementation = true;
7434 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007435 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007436 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007437 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007438 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007439 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007440 }
7441
7442 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007443 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007444 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007445 }
7446
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007447 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007448 HandleCodeCompleteResults(this, CodeCompleter,
7449 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007450 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007451 return;
7452 }
7453
7454 // Find all of the methods that we could declare/implement here.
7455 KnownMethodsMap KnownMethods;
7456 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007457 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007458
Douglas Gregor636a61e2010-04-07 00:21:17 +00007459 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007460 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007461 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007462 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007463 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007464 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007465 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007466 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7467 MEnd = KnownMethods.end();
7468 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007469 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007470 CodeCompletionBuilder Builder(Results.getAllocator(),
7471 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007472
7473 // Add the '-'/'+' prefix if it wasn't provided yet.
7474 if (!IsInstanceMethod) {
7475 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7476 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7477 }
7478
Douglas Gregor636a61e2010-04-07 00:21:17 +00007479 // If the result type was not already provided, add it to the
7480 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007481 if (ReturnType.isNull()) {
7482 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7483 AttributedType::stripOuterNullability(ResTy);
7484 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007485 Method->getObjCDeclQualifier(), Context, Policy,
7486 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007487 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007488
7489 Selector Sel = Method->getSelector();
7490
7491 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007492 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007493 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007494
7495 // Add parameters to the pattern.
7496 unsigned I = 0;
7497 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
7498 PEnd = Method->param_end();
7499 P != PEnd; (void)++P, ++I) {
7500 // Add the part of the selector name.
7501 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007502 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007503 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007504 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7505 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007506 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007507 } else
7508 break;
7509
7510 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007511 QualType ParamType;
7512 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7513 ParamType = (*P)->getType();
7514 else
7515 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007516 ParamType = ParamType.substObjCTypeArgs(Context, {},
7517 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007518 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007519 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007520 (*P)->getObjCDeclQualifier(),
7521 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007522 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007523
7524 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007525 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007526 }
7527
7528 if (Method->isVariadic()) {
7529 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007530 Builder.AddChunk(CodeCompletionString::CK_Comma);
7531 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00007532 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007533
Douglas Gregord37c59d2010-05-28 00:57:46 +00007534 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007535 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007536 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7537 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7538 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007539 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007540 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007541 Builder.AddTextChunk("return");
7542 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7543 Builder.AddPlaceholderChunk("expression");
7544 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007545 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007546 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007547
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007548 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7549 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007550 }
7551
Douglas Gregor416b5752010-08-25 01:08:01 +00007552 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007553 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007554 Priority += CCD_InBaseClass;
7555
Douglas Gregor78254c82012-03-27 23:34:16 +00007556 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007557 }
7558
Douglas Gregor669a25a2011-02-17 00:22:45 +00007559 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
7560 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007561 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007562 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007563 Containers.push_back(SearchDecl);
7564
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007565 VisitedSelectorSet KnownSelectors;
7566 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7567 MEnd = KnownMethods.end();
7568 M != MEnd; ++M)
7569 KnownSelectors.insert(M->first);
7570
7571
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7573 if (!IFace)
7574 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7575 IFace = Category->getClassInterface();
7576
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007577 if (IFace)
7578 for (auto *Cat : IFace->visible_categories())
7579 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007580
7581 if (IsInstanceMethod) {
7582 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7583 for (auto *P : Containers[I]->instance_properties())
7584 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7585 KnownSelectors, Results);
7586 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007587 }
7588
Douglas Gregor636a61e2010-04-07 00:21:17 +00007589 Results.ExitScope();
7590
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007591 HandleCodeCompleteResults(this, CodeCompleter,
7592 CodeCompletionContext::CCC_Other,
7593 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007594}
Douglas Gregor95887f92010-07-08 23:20:03 +00007595
7596void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7597 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007598 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007599 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007600 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007601 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007602 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007603 if (ExternalSource) {
7604 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7605 I != N; ++I) {
7606 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007607 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007608 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007609
7610 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007611 }
7612 }
7613
7614 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007615 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007616 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007617 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007618 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00007619
7620 if (ReturnTy)
7621 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007622
Douglas Gregor95887f92010-07-08 23:20:03 +00007623 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007624 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7625 MEnd = MethodPool.end();
7626 M != MEnd; ++M) {
7627 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7628 &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00007629 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007630 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007631 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007632 continue;
7633
Douglas Gregor45879692010-07-08 23:37:41 +00007634 if (AtParameterName) {
7635 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007636 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007637 if (NumSelIdents &&
7638 NumSelIdents <= MethList->getMethod()->param_size()) {
7639 ParmVarDecl *Param =
7640 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007641 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007642 CodeCompletionBuilder Builder(Results.getAllocator(),
7643 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007644 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007645 Param->getIdentifier()->getName()));
7646 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007647 }
7648 }
7649
7650 continue;
7651 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007652
Nico Weber2e0c8f72014-12-27 03:58:08 +00007653 Result R(MethList->getMethod(),
7654 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007655 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007656 R.AllParametersAreInformative = false;
7657 R.DeclaringEntity = true;
7658 Results.MaybeAddResult(R, CurContext);
7659 }
7660 }
7661
7662 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007663
7664 if (!AtParameterName && !SelIdents.empty() &&
7665 SelIdents.front()->getName().startswith("init")) {
7666 for (const auto &M : PP.macros()) {
7667 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7668 continue;
7669 Results.EnterNewScope();
7670 CodeCompletionBuilder Builder(Results.getAllocator(),
7671 Results.getCodeCompletionTUInfo());
7672 Builder.AddTypedTextChunk(
7673 Builder.getAllocator().CopyString(M.first->getName()));
7674 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7675 CXCursor_MacroDefinition));
7676 Results.ExitScope();
7677 }
7678 }
7679
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007680 HandleCodeCompleteResults(this, CodeCompleter,
7681 CodeCompletionContext::CCC_Other,
7682 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007683}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007684
Douglas Gregorec00a262010-08-24 22:20:20 +00007685void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007686 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007687 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007688 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007689 Results.EnterNewScope();
7690
7691 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007692 CodeCompletionBuilder Builder(Results.getAllocator(),
7693 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007694 Builder.AddTypedTextChunk("if");
7695 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7696 Builder.AddPlaceholderChunk("condition");
7697 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007698
7699 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007700 Builder.AddTypedTextChunk("ifdef");
7701 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7702 Builder.AddPlaceholderChunk("macro");
7703 Results.AddResult(Builder.TakeString());
7704
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007705 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007706 Builder.AddTypedTextChunk("ifndef");
7707 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7708 Builder.AddPlaceholderChunk("macro");
7709 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007710
7711 if (InConditional) {
7712 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007713 Builder.AddTypedTextChunk("elif");
7714 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7715 Builder.AddPlaceholderChunk("condition");
7716 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007717
7718 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007719 Builder.AddTypedTextChunk("else");
7720 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007721
7722 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007723 Builder.AddTypedTextChunk("endif");
7724 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007725 }
7726
7727 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007728 Builder.AddTypedTextChunk("include");
7729 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7730 Builder.AddTextChunk("\"");
7731 Builder.AddPlaceholderChunk("header");
7732 Builder.AddTextChunk("\"");
7733 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007734
7735 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007736 Builder.AddTypedTextChunk("include");
7737 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7738 Builder.AddTextChunk("<");
7739 Builder.AddPlaceholderChunk("header");
7740 Builder.AddTextChunk(">");
7741 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007742
7743 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007744 Builder.AddTypedTextChunk("define");
7745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7746 Builder.AddPlaceholderChunk("macro");
7747 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007748
7749 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007750 Builder.AddTypedTextChunk("define");
7751 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7752 Builder.AddPlaceholderChunk("macro");
7753 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7754 Builder.AddPlaceholderChunk("args");
7755 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7756 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007757
7758 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007759 Builder.AddTypedTextChunk("undef");
7760 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7761 Builder.AddPlaceholderChunk("macro");
7762 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007763
7764 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007765 Builder.AddTypedTextChunk("line");
7766 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7767 Builder.AddPlaceholderChunk("number");
7768 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007769
7770 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007771 Builder.AddTypedTextChunk("line");
7772 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7773 Builder.AddPlaceholderChunk("number");
7774 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7775 Builder.AddTextChunk("\"");
7776 Builder.AddPlaceholderChunk("filename");
7777 Builder.AddTextChunk("\"");
7778 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007779
7780 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007781 Builder.AddTypedTextChunk("error");
7782 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7783 Builder.AddPlaceholderChunk("message");
7784 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007785
7786 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007787 Builder.AddTypedTextChunk("pragma");
7788 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7789 Builder.AddPlaceholderChunk("arguments");
7790 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007791
David Blaikiebbafb8a2012-03-11 07:00:24 +00007792 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007793 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007794 Builder.AddTypedTextChunk("import");
7795 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7796 Builder.AddTextChunk("\"");
7797 Builder.AddPlaceholderChunk("header");
7798 Builder.AddTextChunk("\"");
7799 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007800
7801 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007802 Builder.AddTypedTextChunk("import");
7803 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7804 Builder.AddTextChunk("<");
7805 Builder.AddPlaceholderChunk("header");
7806 Builder.AddTextChunk(">");
7807 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007808 }
7809
7810 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007811 Builder.AddTypedTextChunk("include_next");
7812 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7813 Builder.AddTextChunk("\"");
7814 Builder.AddPlaceholderChunk("header");
7815 Builder.AddTextChunk("\"");
7816 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007817
7818 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007819 Builder.AddTypedTextChunk("include_next");
7820 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7821 Builder.AddTextChunk("<");
7822 Builder.AddPlaceholderChunk("header");
7823 Builder.AddTextChunk(">");
7824 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007825
7826 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007827 Builder.AddTypedTextChunk("warning");
7828 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7829 Builder.AddPlaceholderChunk("message");
7830 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007831
7832 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7833 // completions for them. And __include_macros is a Clang-internal extension
7834 // that we don't want to encourage anyone to use.
7835
7836 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7837 Results.ExitScope();
7838
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007839 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007840 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007841 Results.data(), Results.size());
7842}
7843
7844void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007845 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007846 S->getFnParent()? Sema::PCC_RecoveryInFunction
7847 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007848}
7849
Douglas Gregorec00a262010-08-24 22:20:20 +00007850void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007851 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007852 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007853 IsDefinition? CodeCompletionContext::CCC_MacroName
7854 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007855 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7856 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007857 CodeCompletionBuilder Builder(Results.getAllocator(),
7858 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007859 Results.EnterNewScope();
7860 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7861 MEnd = PP.macro_end();
7862 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007863 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007864 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007865 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7866 CCP_CodePattern,
7867 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007868 }
7869 Results.ExitScope();
7870 } else if (IsDefinition) {
7871 // FIXME: Can we detect when the user just wrote an include guard above?
7872 }
7873
Douglas Gregor0ac41382010-09-23 23:01:17 +00007874 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007875 Results.data(), Results.size());
7876}
7877
Douglas Gregorec00a262010-08-24 22:20:20 +00007878void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007879 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007880 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007881 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007882
7883 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007884 AddMacroResults(PP, Results, true);
Douglas Gregorec00a262010-08-24 22:20:20 +00007885
7886 // defined (<macro>)
7887 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007888 CodeCompletionBuilder Builder(Results.getAllocator(),
7889 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007890 Builder.AddTypedTextChunk("defined");
7891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7892 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7893 Builder.AddPlaceholderChunk("macro");
7894 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7895 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007896 Results.ExitScope();
7897
7898 HandleCodeCompleteResults(this, CodeCompleter,
7899 CodeCompletionContext::CCC_PreprocessorExpression,
7900 Results.data(), Results.size());
7901}
7902
7903void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7904 IdentifierInfo *Macro,
7905 MacroInfo *MacroInfo,
7906 unsigned Argument) {
7907 // FIXME: In the future, we could provide "overload" results, much like we
7908 // do for function calls.
7909
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007910 // Now just ignore this. There will be another code-completion callback
7911 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007912}
7913
Douglas Gregor11583702010-08-25 17:04:25 +00007914void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007915 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007916 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00007917 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00007918}
7919
Alex Lorenzf7f6f822017-05-09 16:05:04 +00007920void Sema::CodeCompleteAvailabilityPlatformName() {
7921 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
7922 CodeCompleter->getCodeCompletionTUInfo(),
7923 CodeCompletionContext::CCC_Other);
7924 Results.EnterNewScope();
7925 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
7926 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
7927 Results.AddResult(CodeCompletionResult(Platform));
7928 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
7929 Twine(Platform) + "ApplicationExtension")));
7930 }
7931 Results.ExitScope();
7932 HandleCodeCompleteResults(this, CodeCompleter,
7933 CodeCompletionContext::CCC_Other, Results.data(),
7934 Results.size());
7935}
7936
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007937void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007938 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007939 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007940 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7941 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007942 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7943 CodeCompletionDeclConsumer Consumer(Builder,
7944 Context.getTranslationUnitDecl());
7945 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7946 Consumer);
7947 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007948
7949 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007950 AddMacroResults(PP, Builder, true);
Douglas Gregorb14904c2010-08-13 22:48:40 +00007951
7952 Results.clear();
7953 Results.insert(Results.end(),
7954 Builder.data(), Builder.data() + Builder.size());
7955}