blob: 7ee24b114cc1166e084a0375383927f254a8a20e [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 }
1423 // Fall through
1424
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);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001641 // Fall through
1642
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 }
1691 // Fall through
1692
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);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003381 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3382 MEnd = Method->end_overridden_methods();
3383 M != MEnd; ++M) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003384 CodeCompletionBuilder Builder(Results.getAllocator(),
3385 Results.getCodeCompletionTUInfo());
Dmitri Gribenko6cfb1532013-02-14 13:53:30 +00003386 const CXXMethodDecl *Overridden = *M;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003387 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3388 continue;
3389
3390 // If we need a nested-name-specifier, add one now.
3391 if (!InContext) {
3392 NestedNameSpecifier *NNS
3393 = getRequiredQualification(S.Context, CurContext,
3394 Overridden->getDeclContext());
3395 if (NNS) {
3396 std::string Str;
3397 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003398 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003399 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003400 }
3401 } else if (!InContext->Equals(Overridden->getDeclContext()))
3402 continue;
3403
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003404 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003405 Overridden->getNameAsString()));
3406 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003407 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003408 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003409 if (FirstParam)
3410 FirstParam = false;
3411 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003412 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003413
Aaron Ballman43b68be2014-03-07 17:50:17 +00003414 Builder.AddPlaceholderChunk(
3415 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003416 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003417 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3418 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003419 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003420 CXCursor_CXXMethod,
3421 CXAvailability_Available,
3422 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003423 Results.Ignore(Overridden);
3424 }
3425}
3426
Douglas Gregor07f43572012-01-29 18:15:03 +00003427void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3428 ModuleIdPath Path) {
3429 typedef CodeCompletionResult Result;
3430 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003431 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003432 CodeCompletionContext::CCC_Other);
3433 Results.EnterNewScope();
3434
3435 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003436 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003437 typedef CodeCompletionResult Result;
3438 if (Path.empty()) {
3439 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003440 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003441 PP.getHeaderSearchInfo().collectAllModules(Modules);
3442 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3443 Builder.AddTypedTextChunk(
3444 Builder.getAllocator().CopyString(Modules[I]->Name));
3445 Results.AddResult(Result(Builder.TakeString(),
3446 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003447 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003448 Modules[I]->isAvailable()
3449 ? CXAvailability_Available
3450 : CXAvailability_NotAvailable));
3451 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003452 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003453 // Load the named module.
3454 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3455 Module::AllVisible,
3456 /*IsInclusionDirective=*/false);
3457 // Enumerate submodules.
3458 if (Mod) {
3459 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3460 SubEnd = Mod->submodule_end();
3461 Sub != SubEnd; ++Sub) {
3462
3463 Builder.AddTypedTextChunk(
3464 Builder.getAllocator().CopyString((*Sub)->Name));
3465 Results.AddResult(Result(Builder.TakeString(),
3466 CCP_Declaration,
Argyrios Kyrtzidis345d05f2013-05-29 18:50:15 +00003467 CXCursor_ModuleImportDecl,
Douglas Gregor07f43572012-01-29 18:15:03 +00003468 (*Sub)->isAvailable()
3469 ? CXAvailability_Available
3470 : CXAvailability_NotAvailable));
3471 }
3472 }
3473 }
3474 Results.ExitScope();
3475 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3476 Results.data(),Results.size());
3477}
3478
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003479void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003480 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003481 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003482 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003483 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003484 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003485
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003486 // Determine how to filter results, e.g., so that the names of
3487 // values (functions, enumerators, function templates, etc.) are
3488 // only allowed where we can have an expression.
3489 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003490 case PCC_Namespace:
3491 case PCC_Class:
3492 case PCC_ObjCInterface:
3493 case PCC_ObjCImplementation:
3494 case PCC_ObjCInstanceVariableList:
3495 case PCC_Template:
3496 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003497 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003498 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003499 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3500 break;
3501
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003502 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003503 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003504 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003505 case PCC_ForInit:
3506 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003507 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003508 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3509 else
3510 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003511
David Blaikiebbafb8a2012-03-11 07:00:24 +00003512 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003513 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003514 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003515
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003516 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003517 // Unfiltered
3518 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003519 }
3520
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003521 // If we are in a C++ non-static member function, check the qualifiers on
3522 // the member function to filter/prioritize the results list.
3523 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3524 if (CurMethod->isInstance())
3525 Results.setObjectTypeQualifiers(
3526 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3527
Douglas Gregorc580c522010-01-14 01:09:38 +00003528 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003529 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3530 CodeCompleter->includeGlobals());
Douglas Gregor92253692009-12-07 09:54:55 +00003531
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003532 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003533 Results.ExitScope();
3534
Douglas Gregorce0e8562010-08-23 21:54:33 +00003535 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003536 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003537 case PCC_Expression:
3538 case PCC_Statement:
3539 case PCC_RecoveryInFunction:
3540 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003541 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003542 break;
3543
3544 case PCC_Namespace:
3545 case PCC_Class:
3546 case PCC_ObjCInterface:
3547 case PCC_ObjCImplementation:
3548 case PCC_ObjCInstanceVariableList:
3549 case PCC_Template:
3550 case PCC_MemberTemplate:
3551 case PCC_ForInit:
3552 case PCC_Condition:
3553 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003554 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003555 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003556 }
3557
Douglas Gregor9eb77012009-11-07 00:00:49 +00003558 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003559 AddMacroResults(PP, Results, false);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003560
Douglas Gregor50832e02010-09-20 22:39:41 +00003561 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003562 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003563}
3564
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003565static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3566 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003567 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003568 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003569 bool IsSuper,
3570 ResultBuilder &Results);
3571
3572void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3573 bool AllowNonIdentifiers,
3574 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003575 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003576 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003577 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003578 AllowNestedNameSpecifiers
3579 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3580 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003581 Results.EnterNewScope();
3582
3583 // Type qualifiers can come after names.
3584 Results.AddResult(Result("const"));
3585 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003586 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003587 Results.AddResult(Result("restrict"));
3588
David Blaikiebbafb8a2012-03-11 07:00:24 +00003589 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003590 if (getLangOpts().CPlusPlus11 &&
3591 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3592 DS.getTypeSpecType() == DeclSpec::TST_struct))
3593 Results.AddResult("final");
3594
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003595 if (AllowNonIdentifiers) {
3596 Results.AddResult(Result("operator"));
3597 }
3598
3599 // Add nested-name-specifiers.
3600 if (AllowNestedNameSpecifiers) {
3601 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003602 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003603 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3604 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3605 CodeCompleter->includeGlobals());
Craig Topperc3ec1492014-05-26 06:22:03 +00003606 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003607 }
3608 }
3609 Results.ExitScope();
3610
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003611 // If we're in a context where we might have an expression (rather than a
3612 // declaration), and what we've seen so far is an Objective-C type that could
3613 // be a receiver of a class message, this may be a class message send with
3614 // the initial opening bracket '[' missing. Add appropriate completions.
3615 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003616 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003617 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003618 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3619 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003620 !DS.isTypeAltiVecVector() &&
3621 S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003622 (S->getFlags() & Scope::DeclScope) != 0 &&
3623 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3624 Scope::FunctionPrototypeScope |
3625 Scope::AtCatchScope)) == 0) {
3626 ParsedType T = DS.getRepAsType();
3627 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003628 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003629 }
3630
Douglas Gregor56ccce02010-08-24 04:59:56 +00003631 // Note that we intentionally suppress macro results here, since we do not
3632 // encourage using macros to produce the names of entities.
3633
Douglas Gregor0ac41382010-09-23 23:01:17 +00003634 HandleCodeCompleteResults(this, CodeCompleter,
3635 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003636 Results.data(), Results.size());
3637}
3638
Douglas Gregor68762e72010-08-23 21:17:50 +00003639struct Sema::CodeCompleteExpressionData {
3640 CodeCompleteExpressionData(QualType PreferredType = QualType())
3641 : PreferredType(PreferredType), IntegralConstantExpression(false),
3642 ObjCCollection(false) { }
3643
3644 QualType PreferredType;
3645 bool IntegralConstantExpression;
3646 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003647 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003648};
3649
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003650/// \brief Perform code-completion in an expression context when we know what
3651/// type we're looking for.
Douglas Gregor68762e72010-08-23 21:17:50 +00003652void Sema::CodeCompleteExpression(Scope *S,
3653 const CodeCompleteExpressionData &Data) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003654 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003655 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003656 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003657 if (Data.ObjCCollection)
3658 Results.setFilter(&ResultBuilder::IsObjCCollection);
3659 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003660 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003661 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003662 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3663 else
3664 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003665
3666 if (!Data.PreferredType.isNull())
3667 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3668
3669 // Ignore any declarations that we were told that we don't care about.
3670 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3671 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003672
3673 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003674 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3675 CodeCompleter->includeGlobals());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003676
3677 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003678 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003679 Results.ExitScope();
3680
Douglas Gregor55b037b2010-07-08 20:55:51 +00003681 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003682 if (!Data.PreferredType.isNull())
3683 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3684 || Data.PreferredType->isMemberPointerType()
3685 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003686
Douglas Gregorce0e8562010-08-23 21:54:33 +00003687 if (S->getFnParent() &&
3688 !Data.ObjCCollection &&
3689 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003690 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003691
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003692 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00003693 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003694 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003695 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3696 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003697 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003698}
3699
Douglas Gregoreda7e542010-09-18 01:28:11 +00003700void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3701 if (E.isInvalid())
3702 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003703 else if (getLangOpts().ObjC1)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003704 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003705}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003706
Douglas Gregorb888acf2010-12-09 23:01:55 +00003707/// \brief The set of properties that have already been added, referenced by
3708/// property name.
3709typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3710
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003711/// \brief Retrieve the container definition, if any?
3712static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3713 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3714 if (Interface->hasDefinition())
3715 return Interface->getDefinition();
3716
3717 return Interface;
3718 }
3719
3720 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3721 if (Protocol->hasDefinition())
3722 return Protocol->getDefinition();
3723
3724 return Protocol;
3725 }
3726 return Container;
3727}
3728
Alex Lorenzbaef8022016-11-09 13:43:18 +00003729/// \brief Adds a block invocation code completion result for the given block
3730/// declaration \p BD.
3731static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3732 CodeCompletionBuilder &Builder,
3733 const NamedDecl *BD,
3734 const FunctionTypeLoc &BlockLoc,
3735 const FunctionProtoTypeLoc &BlockProtoLoc) {
3736 Builder.AddResultTypeChunk(
3737 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3738 Policy, Builder.getAllocator()));
3739
3740 AddTypedNameChunk(Context, Policy, BD, Builder);
3741 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3742
3743 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3744 Builder.AddPlaceholderChunk("...");
3745 } else {
3746 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3747 if (I)
3748 Builder.AddChunk(CodeCompletionString::CK_Comma);
3749
3750 // Format the placeholder string.
3751 std::string PlaceholderStr =
3752 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3753
3754 if (I == N - 1 && BlockProtoLoc &&
3755 BlockProtoLoc.getTypePtr()->isVariadic())
3756 PlaceholderStr += ", ...";
3757
3758 // Add the placeholder string.
3759 Builder.AddPlaceholderChunk(
3760 Builder.getAllocator().CopyString(PlaceholderStr));
3761 }
3762 }
3763
3764 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3765}
3766
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003767static void AddObjCProperties(
3768 const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
3769 bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
3770 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3771 bool IsBaseExprStatement = false, bool IsClassProperty = false) {
John McCall276321a2010-08-25 06:19:51 +00003772 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003773
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003774 // Retrieve the definition.
3775 Container = getContainerDef(Container);
3776
Douglas Gregor9291bad2009-11-18 01:29:26 +00003777 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003778 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003779 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003780 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003781
Alex Lorenzbaef8022016-11-09 13:43:18 +00003782 // FIXME: Provide block invocation completion for non-statement
3783 // expressions.
3784 if (!P->getType().getTypePtr()->isBlockPointerType() ||
3785 !IsBaseExprStatement) {
3786 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3787 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003788 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003789 }
3790
3791 // Block setter and invocation completion is provided only when we are able
3792 // to find the FunctionProtoTypeLoc with parameter names for the block.
3793 FunctionTypeLoc BlockLoc;
3794 FunctionProtoTypeLoc BlockProtoLoc;
3795 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
3796 BlockProtoLoc);
3797 if (!BlockLoc) {
3798 Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
3799 CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003800 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00003801 }
3802
3803 // The default completion result for block properties should be the block
3804 // invocation completion when the base expression is a statement.
3805 CodeCompletionBuilder Builder(Results.getAllocator(),
3806 Results.getCodeCompletionTUInfo());
3807 AddObjCBlockCall(Container->getASTContext(),
3808 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
3809 BlockLoc, BlockProtoLoc);
3810 Results.MaybeAddResult(
3811 Result(Builder.TakeString(), P, Results.getBasePriority(P)),
3812 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003813
3814 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00003815 // statement and the block property is mutable.
3816 if (!P->isReadOnly()) {
3817 CodeCompletionBuilder Builder(Results.getAllocator(),
3818 Results.getCodeCompletionTUInfo());
3819 AddResultTypeChunk(Container->getASTContext(),
3820 getCompletionPrintingPolicy(Results.getSema()), P,
3821 CCContext.getBaseType(), Builder);
3822 Builder.AddTypedTextChunk(
3823 Results.getAllocator().CopyString(P->getName()));
3824 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003825
Alex Lorenzbaef8022016-11-09 13:43:18 +00003826 std::string PlaceholderStr = formatBlockPlaceholder(
3827 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
3828 BlockProtoLoc, /*SuppressBlockName=*/true);
3829 // Add the placeholder string.
3830 Builder.AddPlaceholderChunk(
3831 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003832
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003833 // When completing blocks properties that return void the default
3834 // property completion result should show up before the setter,
3835 // otherwise the setter completion should show up before the default
3836 // property completion, as we normally want to use the result of the
3837 // call.
Alex Lorenzbaef8022016-11-09 13:43:18 +00003838 Results.MaybeAddResult(
3839 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00003840 Results.getBasePriority(P) +
3841 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
3842 ? CCD_BlockPropertySetter
3843 : -CCD_BlockPropertySetter)),
Alex Lorenzbaef8022016-11-09 13:43:18 +00003844 CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003845 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003846 };
3847
3848 if (IsClassProperty) {
3849 for (const auto *P : Container->class_properties())
3850 AddProperty(P);
3851 } else {
3852 for (const auto *P : Container->instance_properties())
3853 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003854 }
Craig Topperc3ec1492014-05-26 06:22:03 +00003855
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003856 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00003857 if (AllowNullaryMethods) {
3858 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003859 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003860 // Adds a method result
3861 const auto AddMethod = [&](const ObjCMethodDecl *M) {
3862 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
3863 if (!Name)
3864 return;
3865 if (!AddedProperties.insert(Name).second)
3866 return;
3867 CodeCompletionBuilder Builder(Results.getAllocator(),
3868 Results.getCodeCompletionTUInfo());
3869 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
3870 Builder.AddTypedTextChunk(
3871 Results.getAllocator().CopyString(Name->getName()));
3872 Results.MaybeAddResult(
3873 Result(Builder.TakeString(), M,
3874 CCP_MemberDeclaration + CCD_MethodAsProperty),
3875 CurContext);
3876 };
3877
3878 if (IsClassProperty) {
3879 for (const auto *M : Container->methods()) {
3880 // Gather the class method that can be used as implicit property
3881 // getters. Methods with arguments or methods that return void aren't
3882 // added to the results as they can't be used as a getter.
3883 if (!M->getSelector().isUnarySelector() ||
3884 M->getReturnType()->isVoidType() || M->isInstanceMethod())
3885 continue;
3886 AddMethod(M);
3887 }
3888 } else {
3889 for (auto *M : Container->methods()) {
3890 if (M->getSelector().isUnarySelector())
3891 AddMethod(M);
3892 }
Douglas Gregor95147142011-05-05 15:50:42 +00003893 }
3894 }
Douglas Gregor95147142011-05-05 15:50:42 +00003895
Douglas Gregor9291bad2009-11-18 01:29:26 +00003896 // Add properties in referenced protocols.
3897 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003898 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003899 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003900 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003901 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003902 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003903 if (AllowCategories) {
3904 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00003905 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003906 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003907 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003908 IsBaseExprStatement, IsClassProperty);
Douglas Gregor5d649882009-11-18 22:32:06 +00003909 }
Aaron Ballman15063e12014-03-13 21:35:02 +00003910
Douglas Gregor9291bad2009-11-18 01:29:26 +00003911 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003912 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003913 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003914 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003915 IsBaseExprStatement, IsClassProperty);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003916
Douglas Gregor9291bad2009-11-18 01:29:26 +00003917 // Look in the superclass.
3918 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003919 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003920 AllowNullaryMethods, CurContext, AddedProperties,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003921 Results, IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003922 } else if (const ObjCCategoryDecl *Category
3923 = dyn_cast<ObjCCategoryDecl>(Container)) {
3924 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00003925 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00003926 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003927 CurContext, AddedProperties, Results,
Alex Lorenzfeafdf62016-12-08 15:09:40 +00003928 IsBaseExprStatement, IsClassProperty);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003929 }
3930}
3931
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003932static void AddRecordMembersCompletionResults(Sema &SemaRef,
3933 ResultBuilder &Results, Scope *S,
3934 QualType BaseType,
3935 RecordDecl *RD) {
3936 // Indicate that we are performing a member access, and the cv-qualifiers
3937 // for the base object type.
3938 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3939
3940 // Access to a C/C++ class, struct, or union.
3941 Results.allowNestedNameSpecifiers();
3942 CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
3943 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00003944 SemaRef.CodeCompleter->includeGlobals(),
3945 /*IncludeDependentBases=*/true);
Alex Lorenz0fe0d982017-05-11 13:41:00 +00003946
3947 if (SemaRef.getLangOpts().CPlusPlus) {
3948 if (!Results.empty()) {
3949 // The "template" keyword can follow "->" or "." in the grammar.
3950 // However, we only want to suggest the template keyword if something
3951 // is dependent.
3952 bool IsDependent = BaseType->isDependentType();
3953 if (!IsDependent) {
3954 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3955 if (DeclContext *Ctx = DepScope->getEntity()) {
3956 IsDependent = Ctx->isDependentContext();
3957 break;
3958 }
3959 }
3960
3961 if (IsDependent)
3962 Results.AddResult(CodeCompletionResult("template"));
3963 }
3964 }
3965}
3966
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003967void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00003968 SourceLocation OpLoc, bool IsArrow,
3969 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003970 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003971 return;
3972
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003973 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3974 if (ConvertedBase.isInvalid())
3975 return;
3976 Base = ConvertedBase.get();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003977
Douglas Gregor2436e712009-09-17 21:32:03 +00003978 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003979
3980 if (IsArrow) {
3981 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3982 BaseType = Ptr->getPointeeType();
3983 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003984 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003985 else
3986 return;
3987 }
3988
Douglas Gregor21325842011-07-07 16:03:39 +00003989 enum CodeCompletionContext::Kind contextKind;
3990
3991 if (IsArrow) {
3992 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3993 }
3994 else {
3995 if (BaseType->isObjCObjectPointerType() ||
3996 BaseType->isObjCObjectOrInterfaceType()) {
3997 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3998 }
3999 else {
4000 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4001 }
4002 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004003
4004 CodeCompletionContext CCContext(contextKind, BaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004005 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004006 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00004007 CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004008 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004009 Results.EnterNewScope();
4010 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004011 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4012 Record->getDecl());
Alex Lorenze6afa392017-05-11 13:48:57 +00004013 } else if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
4014 TemplateName TN = TST->getTemplateName();
4015 if (const auto *TD =
4016 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4017 CXXRecordDecl *RD = TD->getTemplatedDecl();
4018 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
4019 }
4020 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4021 if (auto *RD = ICNT->getDecl())
4022 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD);
Alex Lorenz06cfa992016-10-12 11:40:15 +00004023 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004024 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00004025 AddedPropertiesSet AddedProperties;
Alex Lorenz06cfa992016-10-12 11:40:15 +00004026
4027 if (const ObjCObjectPointerType *ObjCPtr =
4028 BaseType->getAsObjCInterfacePointerType()) {
4029 // Add property results based on our interface.
4030 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4031 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4032 /*AllowNullaryMethods=*/true, CurContext,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004033 AddedProperties, Results, IsBaseExprStatement);
Alex Lorenz06cfa992016-10-12 11:40:15 +00004034 }
4035
Douglas Gregor9291bad2009-11-18 01:29:26 +00004036 // Add properties from the protocols in a qualified interface.
Alex Lorenz06cfa992016-10-12 11:40:15 +00004037 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004038 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004039 CurContext, AddedProperties, Results,
4040 IsBaseExprStatement);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004041 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00004042 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004043 // Objective-C instance variable access.
Craig Topperc3ec1492014-05-26 06:22:03 +00004044 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004045 if (const ObjCObjectPointerType *ObjCPtr
4046 = BaseType->getAs<ObjCObjectPointerType>())
4047 Class = ObjCPtr->getInterfaceDecl();
4048 else
John McCall8b07ec22010-05-15 11:32:37 +00004049 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00004050
4051 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00004052 if (Class) {
4053 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4054 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor39982192010-08-15 06:18:01 +00004055 LookupVisibleDecls(Class, LookupMemberName, Consumer,
4056 CodeCompleter->includeGlobals());
Douglas Gregor9291bad2009-11-18 01:29:26 +00004057 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004058 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00004059
4060 // FIXME: How do we cope with isa?
4061
4062 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004063
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004064 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004065 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004066 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004067 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004068}
4069
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004070void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4071 IdentifierInfo &ClassName,
4072 SourceLocation ClassNameLoc,
4073 bool IsBaseExprStatement) {
4074 IdentifierInfo *ClassNamePtr = &ClassName;
4075 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4076 if (!IFace)
4077 return;
4078 CodeCompletionContext CCContext(
4079 CodeCompletionContext::CCC_ObjCPropertyAccess);
4080 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4081 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4082 &ResultBuilder::IsMember);
4083 Results.EnterNewScope();
4084 AddedPropertiesSet AddedProperties;
4085 AddObjCProperties(CCContext, IFace, true,
4086 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4087 Results, IsBaseExprStatement,
4088 /*IsClassProperty=*/true);
4089 Results.ExitScope();
4090 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4091 Results.data(), Results.size());
4092}
4093
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004094void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
4095 if (!CodeCompleter)
4096 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004097
4098 ResultBuilder::LookupFilter Filter = nullptr;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004099 enum CodeCompletionContext::Kind ContextKind
4100 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004101 switch ((DeclSpec::TST)TagSpec) {
4102 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004103 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004104 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004105 break;
4106
4107 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004108 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004109 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004110 break;
4111
4112 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004113 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004114 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004115 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004116 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004117 break;
4118
4119 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004120 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004121 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004122
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004123 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4124 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004125 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004126
4127 // First pass: look for tags.
4128 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004129 LookupVisibleDecls(S, LookupTagName, Consumer,
4130 CodeCompleter->includeGlobals());
John McCalle87beb22010-04-23 18:46:30 +00004131
Douglas Gregor39982192010-08-15 06:18:01 +00004132 if (CodeCompleter->includeGlobals()) {
4133 // Second pass: look for nested name specifiers.
4134 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
4135 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
4136 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00004137
Douglas Gregor0ac41382010-09-23 23:01:17 +00004138 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004139 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004140}
4141
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004142static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4143 const LangOptions &LangOpts) {
4144 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4145 Results.AddResult("const");
4146 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4147 Results.AddResult("volatile");
4148 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4149 Results.AddResult("restrict");
4150 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4151 Results.AddResult("_Atomic");
4152 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4153 Results.AddResult("__unaligned");
4154}
4155
Douglas Gregor28c78432010-08-27 17:35:51 +00004156void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004157 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004158 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004159 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004160 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004161 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004162 Results.ExitScope();
4163 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004164 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004165 Results.data(), Results.size());
4166}
4167
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004168void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4169 const VirtSpecifiers *VS) {
4170 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4171 CodeCompleter->getCodeCompletionTUInfo(),
4172 CodeCompletionContext::CCC_TypeQualifiers);
4173 Results.EnterNewScope();
4174 AddTypeQualifierResults(DS, Results, LangOpts);
4175 if (LangOpts.CPlusPlus11) {
4176 Results.AddResult("noexcept");
4177 if (D.getContext() == Declarator::MemberContext && !D.isCtorOrDtor() &&
4178 !D.isStaticMember()) {
4179 if (!VS || !VS->isFinalSpecified())
4180 Results.AddResult("final");
4181 if (!VS || !VS->isOverrideSpecified())
4182 Results.AddResult("override");
4183 }
4184 }
4185 Results.ExitScope();
4186 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4187 Results.data(), Results.size());
4188}
4189
Benjamin Kramer72dae622016-02-18 15:30:24 +00004190void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4191 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4192}
4193
Douglas Gregord328d572009-09-21 18:10:23 +00004194void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004195 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004196 return;
John McCall5939b162011-08-06 07:30:58 +00004197
John McCallaab3e412010-08-25 08:40:02 +00004198 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00004199 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4200 if (!type->isEnumeralType()) {
4201 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004202 Data.IntegralConstantExpression = true;
4203 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004204 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004205 }
Douglas Gregord328d572009-09-21 18:10:23 +00004206
4207 // Code-complete the cases of a switch statement over an enumeration type
4208 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004209 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004210 if (EnumDecl *Def = Enum->getDefinition())
4211 Enum = Def;
Douglas Gregord328d572009-09-21 18:10:23 +00004212
4213 // Determine which enumerators we have already seen in the switch statement.
4214 // FIXME: Ideally, we would also be able to look *past* the code-completion
4215 // token, in case we are code-completing in the middle of the switch and not
4216 // at the end. However, we aren't able to do so at the moment.
4217 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004218 NestedNameSpecifier *Qualifier = nullptr;
Douglas Gregord328d572009-09-21 18:10:23 +00004219 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
4220 SC = SC->getNextSwitchCase()) {
4221 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4222 if (!Case)
4223 continue;
4224
4225 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
4226 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4227 if (EnumConstantDecl *Enumerator
4228 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
4229 // We look into the AST of the case statement to determine which
4230 // enumerator was named. Alternatively, we could compute the value of
4231 // the integral constant expression, then compare it against the
4232 // values of each enumerator. However, value-based approach would not
4233 // work as well with C++ templates where enumerators declared within a
4234 // template are type- and value-dependent.
4235 EnumeratorsSeen.insert(Enumerator);
4236
Douglas Gregorf2510672009-09-21 19:57:38 +00004237 // If this is a qualified-id, keep track of the nested-name-specifier
4238 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004239 //
4240 // switch (TagD.getKind()) {
4241 // case TagDecl::TK_enum:
4242 // break;
4243 // case XXX
4244 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004245 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004246 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4247 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004248 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004249 }
4250 }
4251
David Blaikiebbafb8a2012-03-11 07:00:24 +00004252 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00004253 // If there are no prior enumerators in C++, check whether we have to
4254 // qualify the names of the enumerators that we suggest, because they
4255 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004256 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004257 }
4258
Douglas Gregord328d572009-09-21 18:10:23 +00004259 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004260 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004261 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004262 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004263 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004264 for (auto *E : Enum->enumerators()) {
4265 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004266 continue;
4267
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004268 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004269 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004270 }
4271 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004272
Douglas Gregor21325842011-07-07 16:03:39 +00004273 //We need to make sure we're setting the right context,
4274 //so only say we include macros if the code completer says we do
4275 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
4276 if (CodeCompleter->includeMacros()) {
Douglas Gregor8cb17462012-10-09 16:01:50 +00004277 AddMacroResults(PP, Results, false);
Douglas Gregor21325842011-07-07 16:03:39 +00004278 kind = CodeCompletionContext::CCC_OtherWithMacros;
4279 }
4280
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004281 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00004282 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004283 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004284}
4285
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004286static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004287 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004288 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004289
4290 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004291 if (!Args[I])
4292 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004293
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004294 return false;
4295}
4296
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004297typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4298
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004299static void mergeCandidatesWithResults(Sema &SemaRef,
4300 SmallVectorImpl<ResultCandidate> &Results,
4301 OverloadCandidateSet &CandidateSet,
4302 SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004303 if (!CandidateSet.empty()) {
4304 // Sort the overload candidate set by placing the best overloads first.
4305 std::stable_sort(
4306 CandidateSet.begin(), CandidateSet.end(),
4307 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004308 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4309 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004310 });
4311
4312 // Add the remaining viable overload candidates as code-completion results.
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004313 for (auto &Candidate : CandidateSet) {
4314 if (Candidate.Function && Candidate.Function->isDeleted())
4315 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004316 if (Candidate.Viable)
4317 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004318 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004319 }
4320}
4321
4322/// \brief Get the type of the Nth parameter from a given set of overload
4323/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004324static QualType getParamType(Sema &SemaRef,
4325 ArrayRef<ResultCandidate> Candidates,
4326 unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004327
4328 // Given the overloads 'Candidates' for a function call matching all arguments
4329 // up to N, return the type of the Nth parameter if it is the same for all
4330 // overload candidates.
4331 QualType ParamType;
4332 for (auto &Candidate : Candidates) {
4333 if (auto FType = Candidate.getFunctionType())
4334 if (auto Proto = dyn_cast<FunctionProtoType>(FType))
4335 if (N < Proto->getNumParams()) {
4336 if (ParamType.isNull())
4337 ParamType = Proto->getParamType(N);
4338 else if (!SemaRef.Context.hasSameUnqualifiedType(
4339 ParamType.getNonReferenceType(),
4340 Proto->getParamType(N).getNonReferenceType()))
4341 // Otherwise return a default-constructed QualType.
4342 return QualType();
4343 }
4344 }
4345
4346 return ParamType;
4347}
4348
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004349static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S,
4350 MutableArrayRef<ResultCandidate> Candidates,
4351 unsigned CurrentArg,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004352 bool CompleteExpressionWithCurrentArg = true) {
4353 QualType ParamType;
4354 if (CompleteExpressionWithCurrentArg)
4355 ParamType = getParamType(SemaRef, Candidates, CurrentArg);
4356
4357 if (ParamType.isNull())
4358 SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression);
4359 else
4360 SemaRef.CodeCompleteExpression(S, ParamType);
4361
4362 if (!Candidates.empty())
4363 SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg,
4364 Candidates.data(),
4365 Candidates.size());
4366}
4367
4368void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004369 if (!CodeCompleter)
4370 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004371
4372 // When we're code-completing for a call, we fall back to ordinary
4373 // name code-completion whenever we can't produce specific
4374 // results. We may want to revisit this strategy in the future,
4375 // e.g., by merging the two kinds of results.
4376
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004377 // FIXME: Provide support for variadic template functions.
Douglas Gregor3ef59522009-12-11 19:06:04 +00004378
Douglas Gregorcabea402009-09-22 15:41:20 +00004379 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004380 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4381 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004382 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00004383 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00004384 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004385
John McCall57500772009-12-16 12:17:52 +00004386 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004387 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004388 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004389
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004390 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004391
John McCall57500772009-12-16 12:17:52 +00004392 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004393 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004394 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004395 /*PartialOverloading=*/true);
4396 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4397 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4398 if (UME->hasExplicitTemplateArgs()) {
4399 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4400 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004401 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004402
4403 // Add the base as first argument (use a nullptr if the base is implicit).
4404 SmallVector<Expr *, 12> ArgExprs(
4405 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004406 ArgExprs.append(Args.begin(), Args.end());
4407 UnresolvedSet<8> Decls;
4408 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004409 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004410 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4411 /*SuppressUsedConversions=*/false,
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004412 /*PartialOverloading=*/true,
4413 FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004414 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004415 FunctionDecl *FD = nullptr;
4416 if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
4417 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
4418 else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn))
4419 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004420 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004421 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004422 !FD->getType()->getAs<FunctionProtoType>())
4423 Results.push_back(ResultCandidate(FD));
4424 else
4425 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4426 Args, CandidateSet,
4427 /*SuppressUsedConversions=*/false,
4428 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004429
4430 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4431 // If expression's type is CXXRecordDecl, it may overload the function
4432 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004433 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004434 if (isCompleteType(Loc, NakedFn->getType())) {
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004435 DeclarationName OpName = Context.DeclarationNames
4436 .getCXXOperatorName(OO_Call);
4437 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4438 LookupQualifiedName(R, DC);
4439 R.suppressDiagnostics();
4440 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4441 ArgExprs.append(Args.begin(), Args.end());
4442 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4443 /*ExplicitArgs=*/nullptr,
4444 /*SuppressUsedConversions=*/false,
4445 /*PartialOverloading=*/true);
4446 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004447 } else {
4448 // Lastly we check whether expression's type is function pointer or
4449 // function.
4450 QualType T = NakedFn->getType();
4451 if (!T->getPointeeType().isNull())
4452 T = T->getPointeeType();
4453
4454 if (auto FP = T->getAs<FunctionProtoType>()) {
4455 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004456 /*PartialOverloading=*/true) ||
4457 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004458 Results.push_back(ResultCandidate(FP));
4459 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004460 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004461 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004462 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004463 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00004464
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004465 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4466 CodeCompleteOverloadResults(*this, S, Results, Args.size(),
4467 !CandidateSet.empty());
4468}
4469
4470void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
4471 ArrayRef<Expr *> Args) {
4472 if (!CodeCompleter)
4473 return;
4474
4475 // A complete type is needed to lookup for constructors.
Richard Smithdb0ac552015-12-18 22:40:25 +00004476 if (!isCompleteType(Loc, Type))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004477 return;
4478
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004479 CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
4480 if (!RD) {
4481 CodeCompleteExpression(S, Type);
4482 return;
4483 }
4484
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004485 // FIXME: Provide support for member initializers.
4486 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004487
4488 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4489
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004490 for (auto C : LookupConstructors(RD)) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004491 if (auto FD = dyn_cast<FunctionDecl>(C)) {
4492 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()),
4493 Args, CandidateSet,
4494 /*SuppressUsedConversions=*/false,
4495 /*PartialOverloading=*/true);
4496 } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4497 AddTemplateOverloadCandidate(FTD,
4498 DeclAccessPair::make(FTD, C->getAccess()),
4499 /*ExplicitTemplateArgs=*/nullptr,
4500 Args, CandidateSet,
4501 /*SuppressUsedConversions=*/false,
4502 /*PartialOverloading=*/true);
4503 }
4504 }
4505
4506 SmallVector<ResultCandidate, 8> Results;
4507 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
4508 CodeCompleteOverloadResults(*this, S, Results, Args.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00004509}
4510
John McCall48871652010-08-21 09:40:31 +00004511void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4512 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004513 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004514 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004515 return;
4516 }
4517
4518 CodeCompleteExpression(S, VD->getType());
4519}
4520
4521void Sema::CodeCompleteReturn(Scope *S) {
4522 QualType ResultType;
4523 if (isa<BlockDecl>(CurContext)) {
4524 if (BlockScopeInfo *BSI = getCurBlock())
4525 ResultType = BSI->ReturnType;
4526 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004527 ResultType = Function->getReturnType();
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004528 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004529 ResultType = Method->getReturnType();
4530
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004531 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004532 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004533 else
4534 CodeCompleteExpression(S, ResultType);
4535}
4536
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004537void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004538 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004539 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004540 mapCodeCompletionContext(*this, PCC_Statement));
4541 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4542 Results.EnterNewScope();
4543
4544 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4545 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4546 CodeCompleter->includeGlobals());
4547
4548 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
4549
4550 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004551 CodeCompletionBuilder Builder(Results.getAllocator(),
4552 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004553 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004554 if (Results.includeCodePatterns()) {
4555 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4556 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4557 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4558 Builder.AddPlaceholderChunk("statements");
4559 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4560 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4561 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004562 Results.AddResult(Builder.TakeString());
4563
4564 // "else if" block
4565 Builder.AddTypedTextChunk("else");
4566 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4567 Builder.AddTextChunk("if");
4568 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4569 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004570 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004571 Builder.AddPlaceholderChunk("condition");
4572 else
4573 Builder.AddPlaceholderChunk("expression");
4574 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004575 if (Results.includeCodePatterns()) {
4576 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4577 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4578 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4579 Builder.AddPlaceholderChunk("statements");
4580 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4581 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4582 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004583 Results.AddResult(Builder.TakeString());
4584
4585 Results.ExitScope();
4586
4587 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004588 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004589
4590 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00004591 AddMacroResults(PP, Results, false);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004592
4593 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4594 Results.data(),Results.size());
4595}
4596
Richard Trieu2bd04012011-09-09 02:00:50 +00004597void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004598 if (LHS)
4599 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4600 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004601 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004602}
4603
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004604void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00004605 bool EnteringContext) {
4606 if (!SS.getScopeRep() || !CodeCompleter)
4607 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004608
4609 // Always pretend to enter a context to ensure that a dependent type
4610 // resolves to a dependent record.
4611 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004612 if (!Ctx)
4613 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004614
4615 // Try to instantiate any non-dependent declaration contexts before
4616 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004617 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004618 return;
4619
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004620 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004621 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004622 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004623 Results.EnterNewScope();
Douglas Gregor0ac41382010-09-23 23:01:17 +00004624
Douglas Gregor3545ff42009-09-21 16:56:56 +00004625 // The "template" keyword can follow "::" in the grammar, but only
4626 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004627 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004628 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004629 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004630
4631 // Add calls to overridden virtual functions, if there are any.
4632 //
4633 // FIXME: This isn't wonderful, because we don't know whether we're actually
4634 // in a context that permits expressions. This is a general issue with
4635 // qualified-id completions.
4636 if (!EnteringContext)
4637 MaybeAddOverrideCalls(*this, Ctx, Results);
4638 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004639
Douglas Gregorac322ec2010-08-27 21:18:54 +00004640 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004641 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4642 /*IncludeGlobalScope=*/true,
4643 /*IncludeDependentBases=*/true);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004644
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004645 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorc1679ec2011-07-25 17:48:11 +00004646 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004647 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004648}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004649
4650void Sema::CodeCompleteUsing(Scope *S) {
4651 if (!CodeCompleter)
4652 return;
4653
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004654 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004655 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004656 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4657 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004658 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004659
4660 // If we aren't in class scope, we could see the "namespace" keyword.
4661 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004662 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004663
4664 // After "using", we can see anything that would start a
4665 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004666 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004667 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4668 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004669 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004670
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004671 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004672 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004673 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004674}
4675
4676void Sema::CodeCompleteUsingDirective(Scope *S) {
4677 if (!CodeCompleter)
4678 return;
4679
Douglas Gregor3545ff42009-09-21 16:56:56 +00004680 // After "using namespace", we expect to see a namespace name or namespace
4681 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004682 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004683 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004684 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004685 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004686 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004687 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004688 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4689 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004690 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004691 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004692 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004693 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004694}
4695
4696void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4697 if (!CodeCompleter)
4698 return;
4699
Ted Kremenekc37877d2013-10-08 17:08:03 +00004700 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004701 if (!S->getParent())
4702 Ctx = Context.getTranslationUnitDecl();
4703
Douglas Gregor0ac41382010-09-23 23:01:17 +00004704 bool SuppressedGlobalResults
4705 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4706
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004707 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004708 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004709 SuppressedGlobalResults
4710 ? CodeCompletionContext::CCC_Namespace
4711 : CodeCompletionContext::CCC_Other,
4712 &ResultBuilder::IsNamespace);
4713
4714 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004715 // We only want to see those namespaces that have already been defined
4716 // within this scope, because its likely that the user is creating an
4717 // extended namespace declaration. Keep track of the most recent
4718 // definition of each namespace.
4719 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4720 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4721 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4722 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004723 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004724
4725 // Add the most recent definition (or extended definition) of each
4726 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004727 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004728 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004729 NS = OrigToLatest.begin(),
4730 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004731 NS != NSEnd; ++NS)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004732 Results.AddResult(CodeCompletionResult(
Craig Topperc3ec1492014-05-26 06:22:03 +00004733 NS->second, Results.getBasePriority(NS->second),
4734 nullptr),
4735 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004736 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004737 }
4738
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004739 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004740 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004741 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004742}
4743
4744void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4745 if (!CodeCompleter)
4746 return;
4747
Douglas Gregor3545ff42009-09-21 16:56:56 +00004748 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004749 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004750 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004751 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004752 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004753 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004754 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4755 CodeCompleter->includeGlobals());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004756 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004757 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004758 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004759}
4760
Douglas Gregorc811ede2009-09-18 20:05:18 +00004761void Sema::CodeCompleteOperatorName(Scope *S) {
4762 if (!CodeCompleter)
4763 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004764
John McCall276321a2010-08-25 06:19:51 +00004765 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004766 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004767 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004768 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004769 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004770 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004771
Douglas Gregor3545ff42009-09-21 16:56:56 +00004772 // Add the names of overloadable operators.
4773#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4774 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004775 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004776#include "clang/Basic/OperatorKinds.def"
4777
4778 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004779 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004780 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004781 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4782 CodeCompleter->includeGlobals());
Douglas Gregor3545ff42009-09-21 16:56:56 +00004783
4784 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004785 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004786 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004787
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004788 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004789 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004790 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004791}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004792
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004793void Sema::CodeCompleteConstructorInitializer(
4794 Decl *ConstructorD,
4795 ArrayRef <CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004796 if (!ConstructorD)
4797 return;
4798
4799 AdjustDeclIfTemplate(ConstructorD);
4800
4801 CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004802 if (!Constructor)
4803 return;
4804
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004805 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004806 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004807 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004808 Results.EnterNewScope();
4809
4810 // Fill in any already-initialized fields or base classes.
4811 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4812 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004813 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004814 if (Initializers[I]->isBaseInitializer())
4815 InitializedBases.insert(
4816 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4817 else
Francois Pichetd583da02010-12-04 09:14:42 +00004818 InitializedFields.insert(cast<FieldDecl>(
4819 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004820 }
4821
4822 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004823 CodeCompletionBuilder Builder(Results.getAllocator(),
4824 Results.getCodeCompletionTUInfo());
Benjamin Kramera4f8df02015-07-09 15:31:10 +00004825 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004826 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004827 CXXRecordDecl *ClassDecl = Constructor->getParent();
Aaron Ballman574705e2014-03-13 15:41:46 +00004828 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004829 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4830 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004831 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004832 = !Initializers.empty() &&
4833 Initializers.back()->isBaseInitializer() &&
Aaron Ballman574705e2014-03-13 15:41:46 +00004834 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004835 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004836 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004837 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004838
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004839 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004840 Results.getAllocator().CopyString(
Aaron Ballman574705e2014-03-13 15:41:46 +00004841 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004842 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4843 Builder.AddPlaceholderChunk("args");
4844 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4845 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004846 SawLastInitializer? CCP_NextInitializer
4847 : CCP_MemberDeclaration));
4848 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004849 }
4850
4851 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00004852 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004853 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
4854 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004855 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004856 = !Initializers.empty() &&
4857 Initializers.back()->isBaseInitializer() &&
Aaron Ballman445a9392014-03-13 16:15:17 +00004858 Context.hasSameUnqualifiedType(Base.getType(),
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004859 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004860 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004861 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004862
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004863 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004864 Builder.getAllocator().CopyString(
Aaron Ballman445a9392014-03-13 16:15:17 +00004865 Base.getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004866 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4867 Builder.AddPlaceholderChunk("args");
4868 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4869 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004870 SawLastInitializer? CCP_NextInitializer
4871 : CCP_MemberDeclaration));
4872 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004873 }
4874
4875 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004876 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00004877 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
4878 .second) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004879 SawLastInitializer
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00004880 = !Initializers.empty() &&
4881 Initializers.back()->isAnyMemberInitializer() &&
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004882 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004883 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004884 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004885
4886 if (!Field->getDeclName())
4887 continue;
4888
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004889 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004890 Field->getIdentifier()->getName()));
4891 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4892 Builder.AddPlaceholderChunk("args");
4893 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4894 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004895 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004896 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004897 CXCursor_MemberRef,
4898 CXAvailability_Available,
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00004899 Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004900 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004901 }
4902 Results.ExitScope();
4903
Douglas Gregor0ac41382010-09-23 23:01:17 +00004904 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004905 Results.data(), Results.size());
4906}
4907
Douglas Gregord8c61782012-02-15 15:34:24 +00004908/// \brief Determine whether this scope denotes a namespace.
4909static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00004910 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00004911 if (!DC)
4912 return false;
4913
4914 return DC->isFileContext();
4915}
4916
4917void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4918 bool AfterAmpersand) {
4919 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004920 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00004921 CodeCompletionContext::CCC_Other);
4922 Results.EnterNewScope();
4923
4924 // Note what has already been captured.
4925 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4926 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004927 for (const auto &C : Intro.Captures) {
4928 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00004929 IncludedThis = true;
4930 continue;
4931 }
4932
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00004933 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00004934 }
4935
4936 // Look for other capturable variables.
4937 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00004938 for (const auto *D : S->decls()) {
4939 const auto *Var = dyn_cast<VarDecl>(D);
Douglas Gregord8c61782012-02-15 15:34:24 +00004940 if (!Var ||
4941 !Var->hasLocalStorage() ||
4942 Var->hasAttr<BlocksAttr>())
4943 continue;
4944
David Blaikie82e95a32014-11-19 07:49:47 +00004945 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00004946 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00004947 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00004948 }
4949 }
4950
4951 // Add 'this', if it would be valid.
4952 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4953 addThisCompletion(*this, Results);
4954
4955 Results.ExitScope();
4956
4957 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4958 Results.data(), Results.size());
4959}
4960
James Dennett596e4752012-06-14 03:11:41 +00004961/// Macro that optionally prepends an "@" to the string literal passed in via
4962/// Keyword, depending on whether NeedAt is true or false.
4963#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4964
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004965static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004966 ResultBuilder &Results,
4967 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004968 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004969 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004970 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004971
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004972 CodeCompletionBuilder Builder(Results.getAllocator(),
4973 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004974 if (LangOpts.ObjC2) {
4975 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00004976 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004977 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4978 Builder.AddPlaceholderChunk("property");
4979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004980
4981 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00004982 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004983 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4984 Builder.AddPlaceholderChunk("property");
4985 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004986 }
4987}
4988
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004989static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004990 ResultBuilder &Results,
4991 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004992 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004993
4994 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004995 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004996
4997 if (LangOpts.ObjC2) {
4998 // @property
James Dennett596e4752012-06-14 03:11:41 +00004999 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005000
5001 // @required
James Dennett596e4752012-06-14 03:11:41 +00005002 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005003
5004 // @optional
James Dennett596e4752012-06-14 03:11:41 +00005005 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005006 }
5007}
5008
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005009static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005010 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005011 CodeCompletionBuilder Builder(Results.getAllocator(),
5012 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005013
5014 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00005015 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005016 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5017 Builder.AddPlaceholderChunk("name");
5018 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005019
Douglas Gregorf4c33342010-05-28 00:22:41 +00005020 if (Results.includeCodePatterns()) {
5021 // @interface name
5022 // FIXME: Could introduce the whole pattern, including superclasses and
5023 // such.
James Dennett596e4752012-06-14 03:11:41 +00005024 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005025 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5026 Builder.AddPlaceholderChunk("class");
5027 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005028
Douglas Gregorf4c33342010-05-28 00:22:41 +00005029 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00005030 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005031 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5032 Builder.AddPlaceholderChunk("protocol");
5033 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005034
5035 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00005036 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005037 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5038 Builder.AddPlaceholderChunk("class");
5039 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005040 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005041
5042 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00005043 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005044 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5045 Builder.AddPlaceholderChunk("alias");
5046 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5047 Builder.AddPlaceholderChunk("class");
5048 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005049
5050 if (Results.getSema().getLangOpts().Modules) {
5051 // @import name
5052 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5053 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5054 Builder.AddPlaceholderChunk("module");
5055 Results.AddResult(Result(Builder.TakeString()));
5056 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005057}
5058
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005059void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005060 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005061 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005062 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005063 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005064 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005065 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005066 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005067 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005068 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005069 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005070 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005071 HandleCodeCompleteResults(this, CodeCompleter,
5072 CodeCompletionContext::CCC_Other,
5073 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005074}
5075
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005076static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005077 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005078 CodeCompletionBuilder Builder(Results.getAllocator(),
5079 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005080
5081 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005082 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005083 if (Results.getSema().getLangOpts().CPlusPlus ||
5084 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005085 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005086 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00005087 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005088 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5089 Builder.AddPlaceholderChunk("type-name");
5090 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5091 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005092
5093 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005094 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00005095 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005096 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5097 Builder.AddPlaceholderChunk("protocol-name");
5098 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5099 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005100
5101 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005102 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00005103 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005104 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5105 Builder.AddPlaceholderChunk("selector");
5106 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5107 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005108
5109 // @"string"
5110 Builder.AddResultTypeChunk("NSString *");
5111 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
5112 Builder.AddPlaceholderChunk("string");
5113 Builder.AddTextChunk("\"");
5114 Results.AddResult(Result(Builder.TakeString()));
5115
Douglas Gregor951de302012-07-17 23:24:47 +00005116 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005117 Builder.AddResultTypeChunk("NSArray *");
James Dennett596e4752012-06-14 03:11:41 +00005118 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005119 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005120 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5121 Results.AddResult(Result(Builder.TakeString()));
5122
Douglas Gregor951de302012-07-17 23:24:47 +00005123 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005124 Builder.AddResultTypeChunk("NSDictionary *");
James Dennett596e4752012-06-14 03:11:41 +00005125 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005126 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005127 Builder.AddChunk(CodeCompletionString::CK_Colon);
5128 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5129 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005130 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5131 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005132
Douglas Gregor951de302012-07-17 23:24:47 +00005133 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005134 Builder.AddResultTypeChunk("id");
5135 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005136 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005137 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5138 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005139}
5140
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005141static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005142 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005143 CodeCompletionBuilder Builder(Results.getAllocator(),
5144 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00005145
Douglas Gregorf4c33342010-05-28 00:22:41 +00005146 if (Results.includeCodePatterns()) {
5147 // @try { statements } @catch ( declaration ) { statements } @finally
5148 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00005149 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005150 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5151 Builder.AddPlaceholderChunk("statements");
5152 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5153 Builder.AddTextChunk("@catch");
5154 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5155 Builder.AddPlaceholderChunk("parameter");
5156 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5157 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5158 Builder.AddPlaceholderChunk("statements");
5159 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5160 Builder.AddTextChunk("@finally");
5161 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5162 Builder.AddPlaceholderChunk("statements");
5163 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5164 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005165 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005166
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005167 // @throw
James Dennett596e4752012-06-14 03:11:41 +00005168 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005169 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5170 Builder.AddPlaceholderChunk("expression");
5171 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00005172
Douglas Gregorf4c33342010-05-28 00:22:41 +00005173 if (Results.includeCodePatterns()) {
5174 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00005175 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005176 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5177 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5178 Builder.AddPlaceholderChunk("expression");
5179 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5180 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5181 Builder.AddPlaceholderChunk("statements");
5182 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5183 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005184 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005185}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005186
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005187static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00005188 ResultBuilder &Results,
5189 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005190 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00005191 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
5192 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
5193 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005194 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00005195 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005196}
5197
5198void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005199 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005200 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005201 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005202 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005203 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005204 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005205 HandleCodeCompleteResults(this, CodeCompleter,
5206 CodeCompletionContext::CCC_Other,
5207 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005208}
5209
5210void Sema::CodeCompleteObjCAtStatement(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 Gregorf1934162010-01-13 21:24:21 +00005214 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005215 AddObjCStatementResults(Results, false);
5216 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005217 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005218 HandleCodeCompleteResults(this, CodeCompleter,
5219 CodeCompletionContext::CCC_Other,
5220 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005221}
5222
5223void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005224 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005225 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005226 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005227 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005228 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
Douglas Gregore6078da2009-11-19 00:14:45 +00005235/// \brief Determine whether the addition of the given flag to an Objective-C
5236/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005237static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005238 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005239 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005240 return true;
5241
Bill Wendling44426052012-12-20 19:22:21 +00005242 Attributes |= NewFlag;
Douglas Gregore6078da2009-11-19 00:14:45 +00005243
5244 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005245 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5246 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005247 return true;
5248
Jordan Rose53cb2f32012-08-20 20:01:13 +00005249 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendling44426052012-12-20 19:22:21 +00005250 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00005251 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00005252 ObjCDeclSpec::DQ_PR_copy |
Jordan Rose53cb2f32012-08-20 20:01:13 +00005253 ObjCDeclSpec::DQ_PR_retain |
5254 ObjCDeclSpec::DQ_PR_strong |
5255 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregore6078da2009-11-19 00:14:45 +00005256 if (AssignCopyRetMask &&
5257 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005258 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005259 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005260 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005261 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5262 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005263 return true;
5264
5265 return false;
5266}
5267
Douglas Gregor36029f42009-11-18 23:08:07 +00005268void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005269 if (!CodeCompleter)
5270 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005271
Bill Wendling44426052012-12-20 19:22:21 +00005272 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroff936354c2009-10-08 21:55:05 +00005273
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005274 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005275 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005276 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005277 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005278 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005279 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005280 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005281 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005282 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005283 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5284 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005285 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005286 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005287 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005288 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005289 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005290 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005291 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005292 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005293 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005294 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005295 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005296 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005297
5298 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005299 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005300 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005301 Results.AddResult(CodeCompletionResult("weak"));
5302
Bill Wendling44426052012-12-20 19:22:21 +00005303 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005304 CodeCompletionBuilder Setter(Results.getAllocator(),
5305 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005306 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005307 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005308 Setter.AddPlaceholderChunk("method");
5309 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005310 }
Bill Wendling44426052012-12-20 19:22:21 +00005311 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005312 CodeCompletionBuilder Getter(Results.getAllocator(),
5313 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005314 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005315 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005316 Getter.AddPlaceholderChunk("method");
5317 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005318 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005319 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5320 Results.AddResult(CodeCompletionResult("nonnull"));
5321 Results.AddResult(CodeCompletionResult("nullable"));
5322 Results.AddResult(CodeCompletionResult("null_unspecified"));
5323 Results.AddResult(CodeCompletionResult("null_resettable"));
5324 }
Steve Naroff936354c2009-10-08 21:55:05 +00005325 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005326 HandleCodeCompleteResults(this, CodeCompleter,
5327 CodeCompletionContext::CCC_Other,
5328 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005329}
Steve Naroffeae65032009-11-07 02:08:14 +00005330
James Dennettf1243872012-06-17 05:33:25 +00005331/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005332/// via code completion.
5333enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005334 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5335 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
5336 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005337};
5338
Douglas Gregor67c692c2010-08-26 15:07:07 +00005339static bool isAcceptableObjCSelector(Selector Sel,
5340 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005341 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005342 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005343 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005344 if (NumSelIdents > Sel.getNumArgs())
5345 return false;
5346
5347 switch (WantKind) {
5348 case MK_Any: break;
5349 case MK_ZeroArgSelector: return Sel.isUnarySelector();
5350 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
5351 }
5352
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005353 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5354 return false;
5355
Douglas Gregor67c692c2010-08-26 15:07:07 +00005356 for (unsigned I = 0; I != NumSelIdents; ++I)
5357 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5358 return false;
5359
5360 return true;
5361}
5362
Douglas Gregorc8537c52009-11-19 07:41:15 +00005363static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5364 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005365 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005366 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005367 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005368 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005369}
Douglas Gregor1154e272010-09-16 16:06:31 +00005370
5371namespace {
5372 /// \brief A set of selectors, which is used to avoid introducing multiple
5373 /// completions with the same selector into the result set.
5374 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
5375}
5376
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005377/// \brief Add all of the Objective-C methods in the given Objective-C
5378/// container to the set of results.
5379///
5380/// The container will be a class, protocol, category, or implementation of
5381/// any of the above. This mether will recurse to include methods from
5382/// the superclasses of classes along with their categories, protocols, and
5383/// implementations.
5384///
5385/// \param Container the container in which we'll look to find methods.
5386///
James Dennett596e4752012-06-14 03:11:41 +00005387/// \param WantInstanceMethods Whether to add instance methods (only); if
5388/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005389///
5390/// \param CurContext the context in which we're performing the lookup that
5391/// finds methods.
5392///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005393/// \param AllowSameLength Whether we allow a method to be added to the list
5394/// when it has the same number of parameters as we have selector identifiers.
5395///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005396/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005397static void AddObjCMethods(ObjCContainerDecl *Container,
5398 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005399 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005400 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005401 VisitedSelectorSet &Selectors, bool AllowSameLength,
5402 ResultBuilder &Results, bool InOriginalClass = true,
5403 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005404 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005405 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005406 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005407 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005408 for (auto *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005409 // The instance methods on the root class can be messaged via the
5410 // metaclass.
5411 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005412 (IsRootClass && !WantInstanceMethods)) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00005413 // Check whether the selector identifiers we've been given are a
5414 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005415 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005416 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005417
David Blaikie82e95a32014-11-19 07:49:47 +00005418 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005419 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005420
5421 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005422 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005423 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005424 if (!InOriginalClass)
5425 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00005426 Results.MaybeAddResult(R, CurContext);
5427 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005428 }
5429
Douglas Gregorf37c9492010-09-16 15:34:59 +00005430 // Visit the protocols of protocols.
5431 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005432 if (Protocol->hasDefinition()) {
5433 const ObjCList<ObjCProtocolDecl> &Protocols
5434 = Protocol->getReferencedProtocols();
5435 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5436 E = Protocols.end();
5437 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005438 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5439 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005440 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005441 }
5442
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005443 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005444 return;
5445
5446 // Add methods in protocols.
Aaron Ballmana49c5062014-03-13 20:29:09 +00005447 for (auto *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005448 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5449 Selectors, AllowSameLength, Results, false, IsRootClass);
5450
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005451 // Add methods in categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00005452 for (auto *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005453 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005454 CurContext, Selectors, AllowSameLength, Results,
5455 InOriginalClass, IsRootClass);
5456
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005457 // Add a categories protocol methods.
5458 const ObjCList<ObjCProtocolDecl> &Protocols
5459 = CatDecl->getReferencedProtocols();
5460 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5461 E = Protocols.end();
5462 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005463 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5464 Selectors, AllowSameLength, Results, false, IsRootClass);
5465
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005466 // Add methods in category implementations.
5467 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005468 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5469 Selectors, AllowSameLength, Results, InOriginalClass,
5470 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005471 }
5472
5473 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005474 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005475 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005476 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5477 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5478 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005479
5480 // Add methods in our implementation, if any.
5481 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005482 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5483 Selectors, AllowSameLength, Results, InOriginalClass,
5484 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005485}
5486
5487
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005488void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005489 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005490 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005491 if (!Class) {
5492 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005493 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005494 Class = Category->getClassInterface();
5495
5496 if (!Class)
5497 return;
5498 }
5499
5500 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005501 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005502 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005503 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005504 Results.EnterNewScope();
5505
Douglas Gregor1154e272010-09-16 16:06:31 +00005506 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005507 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005508 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005509 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005510 HandleCodeCompleteResults(this, CodeCompleter,
5511 CodeCompletionContext::CCC_Other,
5512 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005513}
5514
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005515void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005516 // Try to find the interface where setters might live.
5517 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005518 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005519 if (!Class) {
5520 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005521 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005522 Class = Category->getClassInterface();
5523
5524 if (!Class)
5525 return;
5526 }
5527
5528 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005529 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005530 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005531 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005532 Results.EnterNewScope();
5533
Douglas Gregor1154e272010-09-16 16:06:31 +00005534 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005535 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005536 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005537
5538 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005539 HandleCodeCompleteResults(this, CodeCompleter,
5540 CodeCompletionContext::CCC_Other,
5541 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005542}
5543
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005544void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5545 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005546 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005547 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005548 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005549 Results.EnterNewScope();
5550
5551 // Add context-sensitive, Objective-C parameter-passing keywords.
5552 bool AddedInOut = false;
5553 if ((DS.getObjCDeclQualifier() &
5554 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5555 Results.AddResult("in");
5556 Results.AddResult("inout");
5557 AddedInOut = true;
5558 }
5559 if ((DS.getObjCDeclQualifier() &
5560 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5561 Results.AddResult("out");
5562 if (!AddedInOut)
5563 Results.AddResult("inout");
5564 }
5565 if ((DS.getObjCDeclQualifier() &
5566 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5567 ObjCDeclSpec::DQ_Oneway)) == 0) {
5568 Results.AddResult("bycopy");
5569 Results.AddResult("byref");
5570 Results.AddResult("oneway");
5571 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005572 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5573 Results.AddResult("nonnull");
5574 Results.AddResult("nullable");
5575 Results.AddResult("null_unspecified");
5576 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00005577
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005578 // If we're completing the return type of an Objective-C method and the
5579 // identifier IBAction refers to a macro, provide a completion item for
5580 // an action, e.g.,
5581 // IBAction)<#selector#>:(id)sender
5582 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005583 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005584 CodeCompletionBuilder Builder(Results.getAllocator(),
5585 Results.getCodeCompletionTUInfo(),
5586 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005587 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005588 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005589 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005590 Builder.AddChunk(CodeCompletionString::CK_Colon);
5591 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005592 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005593 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005594 Builder.AddTextChunk("sender");
5595 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5596 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005597
5598 // If we're completing the return type, provide 'instancetype'.
5599 if (!IsParameter) {
5600 Results.AddResult(CodeCompletionResult("instancetype"));
5601 }
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005602
Douglas Gregor99fa2642010-08-24 01:06:58 +00005603 // Add various builtin type names and specifiers.
5604 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5605 Results.ExitScope();
5606
5607 // Add the various type names
5608 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5609 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5610 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5611 CodeCompleter->includeGlobals());
5612
5613 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005614 AddMacroResults(PP, Results, false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005615
5616 HandleCodeCompleteResults(this, CodeCompleter,
5617 CodeCompletionContext::CCC_Type,
5618 Results.data(), Results.size());
5619}
5620
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005621/// \brief When we have an expression with type "id", we may assume
5622/// that it has some more-specific class type based on knowledge of
5623/// common uses of Objective-C. This routine returns that class type,
5624/// or NULL if no better result could be determined.
5625static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00005626 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005627 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005628 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005629
5630 Selector Sel = Msg->getSelector();
5631 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005632 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005633
5634 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5635 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005636 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005637
5638 ObjCMethodDecl *Method = Msg->getMethodDecl();
5639 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005640 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005641
5642 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005643 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005644 switch (Msg->getReceiverKind()) {
5645 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00005646 if (const ObjCObjectType *ObjType
5647 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5648 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005649 break;
5650
5651 case ObjCMessageExpr::Instance: {
5652 QualType T = Msg->getInstanceReceiver()->getType();
5653 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5654 IFace = Ptr->getInterfaceDecl();
5655 break;
5656 }
5657
5658 case ObjCMessageExpr::SuperInstance:
5659 case ObjCMessageExpr::SuperClass:
5660 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005661 }
5662
5663 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005664 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005665
5666 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5667 if (Method->isInstanceMethod())
5668 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5669 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00005670 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005671 .Case("autorelease", IFace)
5672 .Case("copy", IFace)
5673 .Case("copyWithZone", IFace)
5674 .Case("mutableCopy", IFace)
5675 .Case("mutableCopyWithZone", IFace)
5676 .Case("awakeFromCoder", IFace)
5677 .Case("replacementObjectFromCoder", IFace)
5678 .Case("class", IFace)
5679 .Case("classForCoder", IFace)
5680 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005681 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005682
5683 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5684 .Case("new", IFace)
5685 .Case("alloc", IFace)
5686 .Case("allocWithZone", IFace)
5687 .Case("class", IFace)
5688 .Case("superclass", Super)
Craig Topperc3ec1492014-05-26 06:22:03 +00005689 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005690}
5691
Douglas Gregor6fc04132010-08-27 15:10:57 +00005692// Add a special completion for a message send to "super", which fills in the
5693// most likely case of forwarding all of our arguments to the superclass
5694// function.
5695///
5696/// \param S The semantic analysis object.
5697///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00005698/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00005699/// the "super" keyword. Otherwise, we just need to provide the arguments.
5700///
5701/// \param SelIdents The identifiers in the selector that have already been
5702/// provided as arguments for a send to "super".
5703///
Douglas Gregor6fc04132010-08-27 15:10:57 +00005704/// \param Results The set of results to augment.
5705///
5706/// \returns the Objective-C method declaration that would be invoked by
5707/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005708static ObjCMethodDecl *AddSuperSendCompletion(
5709 Sema &S, bool NeedSuperKeyword,
5710 ArrayRef<IdentifierInfo *> SelIdents,
5711 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005712 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5713 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005714 return nullptr;
5715
Douglas Gregor6fc04132010-08-27 15:10:57 +00005716 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5717 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00005718 return nullptr;
5719
Douglas Gregor6fc04132010-08-27 15:10:57 +00005720 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00005721 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005722 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5723 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005724 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5725 CurMethod->isInstanceMethod());
5726
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005727 // Check in categories or class extensions.
5728 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00005729 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005730 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005731 CurMethod->isInstanceMethod())))
5732 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005733 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005734 }
5735 }
5736
Douglas Gregor6fc04132010-08-27 15:10:57 +00005737 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00005738 return nullptr;
5739
Douglas Gregor6fc04132010-08-27 15:10:57 +00005740 // Check whether the superclass method has the same signature.
5741 if (CurMethod->param_size() != SuperMethod->param_size() ||
5742 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00005743 return nullptr;
5744
Douglas Gregor6fc04132010-08-27 15:10:57 +00005745 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5746 CurPEnd = CurMethod->param_end(),
5747 SuperP = SuperMethod->param_begin();
5748 CurP != CurPEnd; ++CurP, ++SuperP) {
5749 // Make sure the parameter types are compatible.
5750 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5751 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00005752 return nullptr;
5753
Douglas Gregor6fc04132010-08-27 15:10:57 +00005754 // Make sure we have a parameter name to forward!
5755 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00005756 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00005757 }
5758
5759 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005760 CodeCompletionBuilder Builder(Results.getAllocator(),
5761 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005762
5763 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00005764 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5765 Results.getCompletionContext().getBaseType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00005766 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005767
5768 // If we need the "super" keyword, add it (plus some spacing).
5769 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005770 Builder.AddTypedTextChunk("super");
5771 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005772 }
5773
5774 Selector Sel = CurMethod->getSelector();
5775 if (Sel.isUnarySelector()) {
5776 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005777 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005778 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005779 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005780 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005781 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005782 } else {
5783 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5784 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005785 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005786 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005787
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005788 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005789 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005790 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005791 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005792 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005793 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005794 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005795 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005796 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005797 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005798 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005799 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005800 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005801 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005802 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005803 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005804 }
5805 }
5806 }
5807
Douglas Gregor78254c82012-03-27 23:34:16 +00005808 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5809 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005810 return SuperMethod;
5811}
5812
Douglas Gregora817a192010-05-27 23:06:34 +00005813void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005814 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005815 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005816 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005817 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005818 getLangOpts().CPlusPlus11
Douglas Gregord8c61782012-02-15 15:34:24 +00005819 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5820 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005821
Douglas Gregora817a192010-05-27 23:06:34 +00005822 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5823 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005824 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5825 CodeCompleter->includeGlobals());
Douglas Gregora817a192010-05-27 23:06:34 +00005826
5827 // If we are in an Objective-C method inside a class that has a superclass,
5828 // add "super" as an option.
5829 if (ObjCMethodDecl *Method = getCurMethodDecl())
5830 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005831 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005832 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005833
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005834 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005835 }
Douglas Gregora817a192010-05-27 23:06:34 +00005836
Richard Smith2bf7fdb2013-01-02 11:42:31 +00005837 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00005838 addThisCompletion(*this, Results);
5839
Douglas Gregora817a192010-05-27 23:06:34 +00005840 Results.ExitScope();
5841
5842 if (CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00005843 AddMacroResults(PP, Results, false);
Douglas Gregor50832e02010-09-20 22:39:41 +00005844 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005845 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005846
5847}
5848
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005849void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005850 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005851 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005852 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005853 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5854 // Figure out which interface we're in.
5855 CDecl = CurMethod->getClassInterface();
5856 if (!CDecl)
5857 return;
5858
5859 // Find the superclass of this class.
5860 CDecl = CDecl->getSuperClass();
5861 if (!CDecl)
5862 return;
5863
5864 if (CurMethod->isInstanceMethod()) {
5865 // We are inside an instance method, which means that the message
5866 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005867 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00005868 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005869 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005870 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005871 }
5872
5873 // Fall through to send to the superclass in CDecl.
5874 } else {
5875 // "super" may be the name of a type or variable. Figure out which
5876 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00005877 IdentifierInfo *Super = getSuperIdentifier();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005878 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5879 LookupOrdinaryName);
5880 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5881 // "super" names an interface. Use it.
5882 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005883 if (const ObjCObjectType *Iface
5884 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5885 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005886 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5887 // "super" names an unresolved type; we can't be more specific.
5888 } else {
5889 // Assume that "super" names some kind of value and parse that way.
5890 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005891 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005892 UnqualifiedId id;
5893 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005894 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5895 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005896 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005897 SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005898 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005899 }
5900
5901 // Fall through
5902 }
5903
John McCallba7bf592010-08-24 05:47:05 +00005904 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005905 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005906 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005907 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005908 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005909 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005910}
5911
Douglas Gregor74661272010-09-21 00:03:25 +00005912/// \brief Given a set of code-completion results for the argument of a message
5913/// send, determine the preferred type (if any) for that argument expression.
5914static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5915 unsigned NumSelIdents) {
5916 typedef CodeCompletionResult Result;
5917 ASTContext &Context = Results.getSema().Context;
5918
5919 QualType PreferredType;
5920 unsigned BestPriority = CCP_Unlikely * 2;
5921 Result *ResultsData = Results.data();
5922 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5923 Result &R = ResultsData[I];
5924 if (R.Kind == Result::RK_Declaration &&
5925 isa<ObjCMethodDecl>(R.Declaration)) {
5926 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00005927 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00005928 if (NumSelIdents <= Method->param_size()) {
Alp Toker03376dc2014-07-07 09:02:20 +00005929 QualType MyPreferredType = Method->parameters()[NumSelIdents - 1]
Douglas Gregor74661272010-09-21 00:03:25 +00005930 ->getType();
5931 if (R.Priority < BestPriority || PreferredType.isNull()) {
5932 BestPriority = R.Priority;
5933 PreferredType = MyPreferredType;
5934 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5935 MyPreferredType)) {
5936 PreferredType = QualType();
5937 }
5938 }
5939 }
5940 }
5941 }
5942
5943 return PreferredType;
5944}
5945
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005946static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5947 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005948 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005949 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005950 bool IsSuper,
5951 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005952 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00005953 ObjCInterfaceDecl *CDecl = nullptr;
5954
Douglas Gregor8ce33212009-11-17 17:59:40 +00005955 // If the given name refers to an interface type, retrieve the
5956 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005957 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00005958 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005959 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00005960 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5961 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00005962 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005963
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005964 // Add all of the factory methods in this Objective-C class, its protocols,
5965 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00005966 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005967
Douglas Gregor6fc04132010-08-27 15:10:57 +00005968 // If this is a send-to-super, try to add the special "super" send
5969 // completion.
5970 if (IsSuper) {
5971 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005972 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00005973 Results.Ignore(SuperMethod);
5974 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005975
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005976 // If we're inside an Objective-C method definition, prefer its selector to
5977 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005978 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005979 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005980
Douglas Gregor1154e272010-09-16 16:06:31 +00005981 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00005982 if (CDecl)
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005983 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005984 SemaRef.CurContext, Selectors, AtArgumentExpression,
5985 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005986 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00005987 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005988
Douglas Gregord720daf2010-04-06 17:30:22 +00005989 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005990 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00005991 if (SemaRef.getExternalSource()) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005992 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00005993 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00005994 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00005995 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005996 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005997 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005998
5999 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006000 }
6001 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006002
6003 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
6004 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006005 M != MEnd; ++M) {
6006 for (ObjCMethodList *MethList = &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006007 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006008 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006009 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006010 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006011
Nico Weber2e0c8f72014-12-27 03:58:08 +00006012 Result R(MethList->getMethod(),
6013 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006014 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006015 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006016 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006017 }
6018 }
6019 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006020
6021 Results.ExitScope();
6022}
Douglas Gregor6285f752010-04-06 16:40:00 +00006023
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006024void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006025 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006026 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006027 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00006028
6029 QualType T = this->GetTypeFromParser(Receiver);
6030
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006031 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006032 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006033 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006034 T, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006035
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006036 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006037 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00006038
6039 // If we're actually at the argument expression (rather than prior to the
6040 // selector), we're actually performing code completion for an expression.
6041 // Determine whether we have a single, best method. If so, we can
6042 // code-complete the expression using the corresponding parameter type as
6043 // our preferred type, improving completion results.
6044 if (AtArgumentExpression) {
6045 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006046 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006047 if (PreferredType.isNull())
6048 CodeCompleteOrdinaryName(S, PCC_Expression);
6049 else
6050 CodeCompleteExpression(S, PreferredType);
6051 return;
6052 }
6053
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006054 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006055 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006056 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006057}
6058
Richard Trieu2bd04012011-09-09 02:00:50 +00006059void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006060 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006061 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006062 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006063 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00006064
6065 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00006066
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006067 // If necessary, apply function/array conversion to the receiver.
6068 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006069 if (RecExpr) {
6070 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6071 if (Conv.isInvalid()) // conversion failed. bail.
6072 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006073 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006074 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00006075 QualType ReceiverType = RecExpr? RecExpr->getType()
6076 : Super? Context.getObjCObjectPointerType(
6077 Context.getObjCInterfaceType(Super))
6078 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00006079
Douglas Gregordc520b02010-11-08 21:12:30 +00006080 // If we're messaging an expression with type "id" or "Class", check
6081 // whether we know something special about the receiver that allows
6082 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006083 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006084 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6085 if (ReceiverType->isObjCClassType())
6086 return CodeCompleteObjCClassMessage(S,
6087 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006088 SelIdents,
Douglas Gregordc520b02010-11-08 21:12:30 +00006089 AtArgumentExpression, Super);
6090
6091 ReceiverType = Context.getObjCObjectPointerType(
6092 Context.getObjCInterfaceType(IFace));
6093 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006094 } else if (RecExpr && getLangOpts().CPlusPlus) {
6095 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6096 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006097 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006098 ReceiverType = RecExpr->getType();
6099 }
6100 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006101
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006102 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006103 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006104 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00006105 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006106 ReceiverType, SelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00006107
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006108 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006109
Douglas Gregor6fc04132010-08-27 15:10:57 +00006110 // If this is a send-to-super, try to add the special "super" send
6111 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006112 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006113 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006114 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006115 Results.Ignore(SuperMethod);
6116 }
6117
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006118 // If we're inside an Objective-C method definition, prefer its selector to
6119 // others.
6120 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6121 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006122
Douglas Gregor1154e272010-09-16 16:06:31 +00006123 // Keep track of the selectors we've already added.
6124 VisitedSelectorSet Selectors;
6125
Douglas Gregora3329fa2009-11-18 00:06:18 +00006126 // Handle messages to Class. This really isn't a message to an instance
6127 // method, so we treat it the same way we would treat a message send to a
6128 // class method.
6129 if (ReceiverType->isObjCClassType() ||
6130 ReceiverType->isObjCQualifiedClassType()) {
6131 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6132 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006133 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006134 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006135 }
6136 }
6137 // Handle messages to a qualified ID ("id<foo>").
6138 else if (const ObjCObjectPointerType *QualID
6139 = ReceiverType->getAsObjCQualifiedIdType()) {
6140 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006141 for (auto *I : QualID->quals())
6142 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006143 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006144 }
6145 // Handle messages to a pointer to interface type.
6146 else if (const ObjCObjectPointerType *IFacePtr
6147 = ReceiverType->getAsObjCInterfacePointerType()) {
6148 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006149 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006150 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006151 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006152
6153 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006154 for (auto *I : IFacePtr->quals())
6155 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00006156 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006157 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006158 // Handle messages to "id".
6159 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006160 // We're messaging "id", so provide all instance methods we know
6161 // about as code-completion results.
6162
6163 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006164 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006165 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006166 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6167 I != N; ++I) {
6168 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006169 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006170 continue;
6171
Sebastian Redl75d8a322010-08-02 23:18:59 +00006172 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006173 }
6174 }
6175
Sebastian Redl75d8a322010-08-02 23:18:59 +00006176 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6177 MEnd = MethodPool.end();
6178 M != MEnd; ++M) {
6179 for (ObjCMethodList *MethList = &M->second.first;
Nico Weber2e0c8f72014-12-27 03:58:08 +00006180 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00006181 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006182 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006183 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00006184
Nico Weber2e0c8f72014-12-27 03:58:08 +00006185 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006186 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006187
Nico Weber2e0c8f72014-12-27 03:58:08 +00006188 Result R(MethList->getMethod(),
6189 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006190 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006191 R.AllParametersAreInformative = false;
6192 Results.MaybeAddResult(R, CurContext);
6193 }
6194 }
6195 }
Steve Naroffeae65032009-11-07 02:08:14 +00006196 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00006197
6198
6199 // If we're actually at the argument expression (rather than prior to the
6200 // selector), we're actually performing code completion for an expression.
6201 // Determine whether we have a single, best method. If so, we can
6202 // code-complete the expression using the corresponding parameter type as
6203 // our preferred type, improving completion results.
6204 if (AtArgumentExpression) {
6205 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006206 SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006207 if (PreferredType.isNull())
6208 CodeCompleteOrdinaryName(S, PCC_Expression);
6209 else
6210 CodeCompleteExpression(S, PreferredType);
6211 return;
6212 }
6213
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006214 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00006215 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006216 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006217}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006218
Douglas Gregor68762e72010-08-23 21:17:50 +00006219void Sema::CodeCompleteObjCForCollection(Scope *S,
6220 DeclGroupPtrTy IterationVar) {
6221 CodeCompleteExpressionData Data;
6222 Data.ObjCCollection = true;
6223
6224 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006225 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006226 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6227 if (*I)
6228 Data.IgnoreDecls.push_back(*I);
6229 }
6230 }
6231
6232 CodeCompleteExpression(S, Data);
6233}
6234
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006235void Sema::CodeCompleteObjCSelector(Scope *S,
6236 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006237 // If we have an external source, load the entire class method
6238 // pool from the AST file.
6239 if (ExternalSource) {
6240 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6241 I != N; ++I) {
6242 Selector Sel = ExternalSource->GetExternalSelector(I);
6243 if (Sel.isNull() || MethodPool.count(Sel))
6244 continue;
6245
6246 ReadMethodPool(Sel);
6247 }
6248 }
6249
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006250 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006251 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006252 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006253 Results.EnterNewScope();
6254 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6255 MEnd = MethodPool.end();
6256 M != MEnd; ++M) {
6257
6258 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006259 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006260 continue;
6261
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006262 CodeCompletionBuilder Builder(Results.getAllocator(),
6263 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006264 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006265 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006266 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006267 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006268 continue;
6269 }
6270
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006271 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006272 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006273 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006274 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006275 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006276 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006277 Accumulator.clear();
6278 }
6279 }
6280
Benjamin Kramer632500c2011-07-26 16:59:25 +00006281 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006282 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006283 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006284 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006285 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006286 }
6287 Results.ExitScope();
6288
6289 HandleCodeCompleteResults(this, CodeCompleter,
6290 CodeCompletionContext::CCC_SelectorName,
6291 Results.data(), Results.size());
6292}
6293
Douglas Gregorbaf69612009-11-18 04:19:12 +00006294/// \brief Add all of the protocol declarations that we find in the given
6295/// (translation unit) context.
6296static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006297 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006298 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006299 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00006300
Aaron Ballman629afae2014-03-07 19:56:05 +00006301 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006302 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006303 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006304 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Craig Topperc3ec1492014-05-26 06:22:03 +00006305 Results.AddResult(Result(Proto, Results.getBasePriority(Proto),nullptr),
6306 CurContext, nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006307 }
6308}
6309
Craig Topper883dd332015-12-24 23:58:11 +00006310void Sema::CodeCompleteObjCProtocolReferences(
6311 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006312 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006313 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006314 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006315
Chandler Carruthede11632016-11-04 06:06:50 +00006316 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006317 Results.EnterNewScope();
6318
6319 // Tell the result set to ignore all of the protocols we have
6320 // already seen.
6321 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006322 for (const IdentifierLocPair &Pair : Protocols)
6323 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first,
6324 Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006325 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006326
Douglas Gregora3b23b02010-12-09 21:44:02 +00006327 // Add all protocols.
6328 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6329 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006330
Douglas Gregora3b23b02010-12-09 21:44:02 +00006331 Results.ExitScope();
6332 }
6333
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006334 HandleCodeCompleteResults(this, CodeCompleter,
6335 CodeCompletionContext::CCC_ObjCProtocolName,
6336 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006337}
6338
6339void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006340 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006341 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006342 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006343
Chandler Carruthede11632016-11-04 06:06:50 +00006344 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006345 Results.EnterNewScope();
6346
6347 // Add all protocols.
6348 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6349 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006350
Douglas Gregora3b23b02010-12-09 21:44:02 +00006351 Results.ExitScope();
6352 }
6353
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006354 HandleCodeCompleteResults(this, CodeCompleter,
6355 CodeCompletionContext::CCC_ObjCProtocolName,
6356 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006357}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006358
6359/// \brief Add all of the Objective-C interface declarations that we find in
6360/// the given (translation unit) context.
6361static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6362 bool OnlyForwardDeclarations,
6363 bool OnlyUnimplemented,
6364 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006365 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00006366
Aaron Ballman629afae2014-03-07 19:56:05 +00006367 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006368 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006369 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006370 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006371 (!OnlyUnimplemented || !Class->getImplementation()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006372 Results.AddResult(Result(Class, Results.getBasePriority(Class),nullptr),
6373 CurContext, nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006374 }
6375}
6376
6377void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006378 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006379 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006380 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006381 Results.EnterNewScope();
6382
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006383 if (CodeCompleter->includeGlobals()) {
6384 // Add all classes.
6385 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6386 false, Results);
6387 }
6388
Douglas Gregor49c22a72009-11-18 16:26:39 +00006389 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006390
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006391 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006392 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006393 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006394}
6395
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006396void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
6397 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006398 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006399 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006400 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006401 Results.EnterNewScope();
6402
6403 // Make sure that we ignore the class we're currently defining.
6404 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006405 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006406 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006407 Results.Ignore(CurClass);
6408
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006409 if (CodeCompleter->includeGlobals()) {
6410 // Add all classes.
6411 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6412 false, Results);
6413 }
6414
Douglas Gregor49c22a72009-11-18 16:26:39 +00006415 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006416
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006417 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006418 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006419 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006420}
6421
6422void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006423 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006424 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006425 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006426 Results.EnterNewScope();
6427
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006428 if (CodeCompleter->includeGlobals()) {
6429 // Add all unimplemented classes.
6430 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6431 true, Results);
6432 }
6433
Douglas Gregor49c22a72009-11-18 16:26:39 +00006434 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006435
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006436 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006437 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006438 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006439}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006440
6441void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006442 IdentifierInfo *ClassName,
6443 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006444 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006445
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006446 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006447 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006448 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006449
6450 // Ignore any categories we find that have already been implemented by this
6451 // interface.
6452 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6453 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006454 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006455 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006456 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006457 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006458 }
6459
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006460 // Add all of the categories we know about.
6461 Results.EnterNewScope();
6462 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Aaron Ballman629afae2014-03-07 19:56:05 +00006463 for (const auto *D : TU->decls())
6464 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006465 if (CategoryNames.insert(Category->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006466 Results.AddResult(Result(Category, Results.getBasePriority(Category),
6467 nullptr),
6468 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006469 Results.ExitScope();
6470
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006471 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006472 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006473 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006474}
6475
6476void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006477 IdentifierInfo *ClassName,
6478 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006479 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006480
6481 // Find the corresponding interface. If we couldn't find the interface, the
6482 // program itself is ill-formed. However, we'll try to be helpful still by
6483 // providing the list of all of the categories we know about.
6484 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006485 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006486 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6487 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006488 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006489
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006490 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006491 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006492 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006493
6494 // Add all of the categories that have have corresponding interface
6495 // declarations in this class and any of its superclasses, except for
6496 // already-implemented categories in the class itself.
6497 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6498 Results.EnterNewScope();
6499 bool IgnoreImplemented = true;
6500 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006501 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006502 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006503 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006504 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6505 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006506 }
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006507
6508 Class = Class->getSuperClass();
6509 IgnoreImplemented = false;
6510 }
6511 Results.ExitScope();
6512
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006513 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00006514 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006515 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006516}
Douglas Gregor5d649882009-11-18 22:32:06 +00006517
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006518void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006519 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006520 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006521 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00006522 CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006523
6524 // Figure out where this @synthesize lives.
6525 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006526 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006527 if (!Container ||
6528 (!isa<ObjCImplementationDecl>(Container) &&
6529 !isa<ObjCCategoryImplDecl>(Container)))
6530 return;
6531
6532 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006533 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006534 for (const auto *D : Container->decls())
6535 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006536 Results.Ignore(PropertyImpl->getPropertyDecl());
6537
6538 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006539 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006540 Results.EnterNewScope();
6541 if (ObjCImplementationDecl *ClassImpl
6542 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006543 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Douglas Gregor95147142011-05-05 15:50:42 +00006544 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006545 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006546 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006547 AddObjCProperties(CCContext,
6548 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00006549 false, /*AllowNullaryMethods=*/false, CurContext,
6550 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006551 Results.ExitScope();
6552
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006553 HandleCodeCompleteResults(this, CodeCompleter,
6554 CodeCompletionContext::CCC_Other,
6555 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006556}
6557
6558void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006559 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006560 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006561 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006562 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006563 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006564
6565 // Figure out where this @synthesize lives.
6566 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006567 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006568 if (!Container ||
6569 (!isa<ObjCImplementationDecl>(Container) &&
6570 !isa<ObjCCategoryImplDecl>(Container)))
6571 return;
6572
6573 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006574 ObjCInterfaceDecl *Class = nullptr;
Douglas Gregor5d649882009-11-18 22:32:06 +00006575 if (ObjCImplementationDecl *ClassImpl
Manman Ren5b786402016-01-28 18:49:28 +00006576 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006577 Class = ClassImpl->getClassInterface();
6578 else
6579 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6580 ->getClassInterface();
6581
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006582 // Determine the type of the property we're synthesizing.
6583 QualType PropertyType = Context.getObjCIdType();
6584 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006585 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6586 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006587 PropertyType
6588 = Property->getType().getNonReferenceType().getUnqualifiedType();
6589
6590 // Give preference to ivars
6591 Results.setPreferredType(PropertyType);
6592 }
6593 }
6594
Douglas Gregor5d649882009-11-18 22:32:06 +00006595 // Add all of the instance variables in this class and its superclasses.
6596 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006597 bool SawSimilarlyNamedIvar = false;
6598 std::string NameWithPrefix;
6599 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006600 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006601 std::string NameWithSuffix = PropertyName->getName().str();
6602 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00006603 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006604 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6605 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006606 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6607 CurContext, nullptr, false);
6608
Douglas Gregor331faa02011-04-18 14:13:53 +00006609 // Determine whether we've seen an ivar with a name similar to the
6610 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006611 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006612 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006613 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006614 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006615
6616 // Reduce the priority of this result by one, to give it a slight
6617 // advantage over other results whose names don't match so closely.
6618 if (Results.size() &&
6619 Results.data()[Results.size() - 1].Kind
6620 == CodeCompletionResult::RK_Declaration &&
6621 Results.data()[Results.size() - 1].Declaration == Ivar)
6622 Results.data()[Results.size() - 1].Priority--;
6623 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006624 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006625 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006626
6627 if (!SawSimilarlyNamedIvar) {
6628 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006629 // an ivar of the appropriate type.
6630 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006631 typedef CodeCompletionResult Result;
6632 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006633 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6634 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006635
Douglas Gregor75acd922011-09-27 23:30:47 +00006636 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006637 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006638 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006639 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6640 Results.AddResult(Result(Builder.TakeString(), Priority,
6641 CXCursor_ObjCIvarDecl));
6642 }
6643
Douglas Gregor5d649882009-11-18 22:32:06 +00006644 Results.ExitScope();
6645
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006646 HandleCodeCompleteResults(this, CodeCompleter,
6647 CodeCompletionContext::CCC_Other,
6648 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006649}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006650
Douglas Gregor416b5752010-08-25 01:08:01 +00006651// Mapping from selectors to the methods that implement that selector, along
6652// with the "in original class" flag.
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006653typedef llvm::DenseMap<
6654 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006655
6656/// \brief Find all of the methods that reside in the given container
6657/// (and its superclasses, protocols, etc.) that meet the given
6658/// criteria. Insert those methods into the map of known methods,
6659/// indexed by selector so they can be easily found.
6660static void FindImplementableMethods(ASTContext &Context,
6661 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006662 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006663 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006664 KnownMethodsMap &KnownMethods,
6665 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006666 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006667 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006668 if (!IFace->hasDefinition())
6669 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006670
6671 IFace = IFace->getDefinition();
6672 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006673
Douglas Gregor636a61e2010-04-07 00:21:17 +00006674 const ObjCList<ObjCProtocolDecl> &Protocols
6675 = IFace->getReferencedProtocols();
6676 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006677 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006678 I != E; ++I)
6679 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006680 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006681
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006682 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006683 for (auto *Cat : IFace->visible_categories()) {
6684 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006685 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006686 }
6687
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006688 // Visit the superclass.
6689 if (IFace->getSuperClass())
6690 FindImplementableMethods(Context, IFace->getSuperClass(),
6691 WantInstanceMethods, ReturnType,
6692 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006693 }
6694
6695 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6696 // Recurse into protocols.
6697 const ObjCList<ObjCProtocolDecl> &Protocols
6698 = Category->getReferencedProtocols();
6699 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006700 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006701 I != E; ++I)
6702 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006703 KnownMethods, InOriginalClass);
6704
6705 // If this category is the original class, jump to the interface.
6706 if (InOriginalClass && Category->getClassInterface())
6707 FindImplementableMethods(Context, Category->getClassInterface(),
6708 WantInstanceMethods, ReturnType, KnownMethods,
6709 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006710 }
6711
6712 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006713 // Make sure we have a definition; that's what we'll walk.
6714 if (!Protocol->hasDefinition())
6715 return;
6716 Protocol = Protocol->getDefinition();
6717 Container = Protocol;
6718
6719 // Recurse into protocols.
6720 const ObjCList<ObjCProtocolDecl> &Protocols
6721 = Protocol->getReferencedProtocols();
6722 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6723 E = Protocols.end();
6724 I != E; ++I)
6725 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6726 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006727 }
6728
6729 // Add methods in this container. This operation occurs last because
6730 // we want the methods from this container to override any methods
6731 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006732 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00006733 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006734 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00006735 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006736 continue;
6737
Benjamin Kramereb8c4462013-06-29 17:52:13 +00006738 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00006739 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006740 }
6741 }
6742}
6743
Douglas Gregor669a25a2011-02-17 00:22:45 +00006744/// \brief Add the parenthesized return or parameter type chunk to a code
6745/// completion string.
6746static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006747 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006748 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006749 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006750 CodeCompletionBuilder &Builder) {
6751 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00006752 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00006753 if (!Quals.empty())
6754 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006755 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006756 Builder.getAllocator()));
6757 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6758}
6759
6760/// \brief Determine whether the given class is or inherits from a class by
6761/// the given name.
6762static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006763 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006764 if (!Class)
6765 return false;
6766
6767 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6768 return true;
6769
6770 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6771}
6772
6773/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6774/// Key-Value Observing (KVO).
6775static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6776 bool IsInstanceMethod,
6777 QualType ReturnType,
6778 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006779 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006780 ResultBuilder &Results) {
6781 IdentifierInfo *PropName = Property->getIdentifier();
6782 if (!PropName || PropName->getLength() == 0)
6783 return;
6784
Douglas Gregor75acd922011-09-27 23:30:47 +00006785 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6786
Douglas Gregor669a25a2011-02-17 00:22:45 +00006787 // Builder that will create each code completion.
6788 typedef CodeCompletionResult Result;
6789 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006790 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006791
6792 // The selector table.
6793 SelectorTable &Selectors = Context.Selectors;
6794
6795 // The property name, copied into the code completion allocation region
6796 // on demand.
6797 struct KeyHolder {
6798 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006799 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006800 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00006801
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006802 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Craig Topperc3ec1492014-05-26 06:22:03 +00006803 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
6804
Douglas Gregor669a25a2011-02-17 00:22:45 +00006805 operator const char *() {
6806 if (CopiedKey)
6807 return CopiedKey;
6808
6809 return CopiedKey = Allocator.CopyString(Key);
6810 }
6811 } Key(Allocator, PropName->getName());
6812
6813 // The uppercased name of the property name.
6814 std::string UpperKey = PropName->getName();
6815 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00006816 UpperKey[0] = toUppercase(UpperKey[0]);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006817
6818 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6819 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6820 Property->getType());
6821 bool ReturnTypeMatchesVoid
6822 = ReturnType.isNull() || ReturnType->isVoidType();
6823
6824 // Add the normal accessor -(type)key.
6825 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00006826 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006827 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6828 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006829 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6830 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006831
6832 Builder.AddTypedTextChunk(Key);
6833 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6834 CXCursor_ObjCInstanceMethodDecl));
6835 }
6836
6837 // If we have an integral or boolean property (or the user has provided
6838 // an integral or boolean return type), add the accessor -(type)isKey.
6839 if (IsInstanceMethod &&
6840 ((!ReturnType.isNull() &&
6841 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6842 (ReturnType.isNull() &&
6843 (Property->getType()->isIntegerType() ||
6844 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006845 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006846 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006847 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6848 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006849 if (ReturnType.isNull()) {
6850 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6851 Builder.AddTextChunk("BOOL");
6852 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6853 }
6854
6855 Builder.AddTypedTextChunk(
6856 Allocator.CopyString(SelectorId->getName()));
6857 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6858 CXCursor_ObjCInstanceMethodDecl));
6859 }
6860 }
6861
6862 // Add the normal mutator.
6863 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6864 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006865 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006866 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006867 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006868 if (ReturnType.isNull()) {
6869 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6870 Builder.AddTextChunk("void");
6871 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6872 }
6873
6874 Builder.AddTypedTextChunk(
6875 Allocator.CopyString(SelectorId->getName()));
6876 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006877 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6878 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006879 Builder.AddTextChunk(Key);
6880 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6881 CXCursor_ObjCInstanceMethodDecl));
6882 }
6883 }
6884
6885 // Indexed and unordered accessors
6886 unsigned IndexedGetterPriority = CCP_CodePattern;
6887 unsigned IndexedSetterPriority = CCP_CodePattern;
6888 unsigned UnorderedGetterPriority = CCP_CodePattern;
6889 unsigned UnorderedSetterPriority = CCP_CodePattern;
6890 if (const ObjCObjectPointerType *ObjCPointer
6891 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6892 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6893 // If this interface type is not provably derived from a known
6894 // collection, penalize the corresponding completions.
6895 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6896 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6897 if (!InheritsFromClassNamed(IFace, "NSArray"))
6898 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6899 }
6900
6901 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6902 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6903 if (!InheritsFromClassNamed(IFace, "NSSet"))
6904 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6905 }
6906 }
6907 } else {
6908 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6909 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6910 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6911 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6912 }
6913
6914 // Add -(NSUInteger)countOf<key>
6915 if (IsInstanceMethod &&
6916 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006917 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006918 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006919 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
6920 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006921 if (ReturnType.isNull()) {
6922 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6923 Builder.AddTextChunk("NSUInteger");
6924 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6925 }
6926
6927 Builder.AddTypedTextChunk(
6928 Allocator.CopyString(SelectorId->getName()));
6929 Results.AddResult(Result(Builder.TakeString(),
6930 std::min(IndexedGetterPriority,
6931 UnorderedGetterPriority),
6932 CXCursor_ObjCInstanceMethodDecl));
6933 }
6934 }
6935
6936 // Indexed getters
6937 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6938 if (IsInstanceMethod &&
6939 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006940 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006941 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006942 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006943 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006944 if (ReturnType.isNull()) {
6945 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6946 Builder.AddTextChunk("id");
6947 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6948 }
6949
6950 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6951 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6952 Builder.AddTextChunk("NSUInteger");
6953 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6954 Builder.AddTextChunk("index");
6955 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6956 CXCursor_ObjCInstanceMethodDecl));
6957 }
6958 }
6959
6960 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6961 if (IsInstanceMethod &&
6962 (ReturnType.isNull() ||
6963 (ReturnType->isObjCObjectPointerType() &&
6964 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6965 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6966 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006967 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006968 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006969 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00006970 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006971 if (ReturnType.isNull()) {
6972 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6973 Builder.AddTextChunk("NSArray *");
6974 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6975 }
6976
6977 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6978 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6979 Builder.AddTextChunk("NSIndexSet *");
6980 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6981 Builder.AddTextChunk("indexes");
6982 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6983 CXCursor_ObjCInstanceMethodDecl));
6984 }
6985 }
6986
6987 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6988 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006989 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006990 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006991 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006992 &Context.Idents.get("range")
6993 };
6994
David Blaikie82e95a32014-11-19 07:49:47 +00006995 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006996 if (ReturnType.isNull()) {
6997 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6998 Builder.AddTextChunk("void");
6999 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7000 }
7001
7002 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7003 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7004 Builder.AddPlaceholderChunk("object-type");
7005 Builder.AddTextChunk(" **");
7006 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7007 Builder.AddTextChunk("buffer");
7008 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7009 Builder.AddTypedTextChunk("range:");
7010 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7011 Builder.AddTextChunk("NSRange");
7012 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7013 Builder.AddTextChunk("inRange");
7014 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
7015 CXCursor_ObjCInstanceMethodDecl));
7016 }
7017 }
7018
7019 // Mutable indexed accessors
7020
7021 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7022 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007023 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007024 IdentifierInfo *SelectorIds[2] = {
7025 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007026 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007027 };
7028
David Blaikie82e95a32014-11-19 07:49:47 +00007029 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007030 if (ReturnType.isNull()) {
7031 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7032 Builder.AddTextChunk("void");
7033 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7034 }
7035
7036 Builder.AddTypedTextChunk("insertObject:");
7037 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7038 Builder.AddPlaceholderChunk("object-type");
7039 Builder.AddTextChunk(" *");
7040 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7041 Builder.AddTextChunk("object");
7042 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7043 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7044 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7045 Builder.AddPlaceholderChunk("NSUInteger");
7046 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7047 Builder.AddTextChunk("index");
7048 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7049 CXCursor_ObjCInstanceMethodDecl));
7050 }
7051 }
7052
7053 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7054 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007055 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007056 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007057 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007058 &Context.Idents.get("atIndexes")
7059 };
7060
David Blaikie82e95a32014-11-19 07:49:47 +00007061 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007062 if (ReturnType.isNull()) {
7063 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7064 Builder.AddTextChunk("void");
7065 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7066 }
7067
7068 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7069 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7070 Builder.AddTextChunk("NSArray *");
7071 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7072 Builder.AddTextChunk("array");
7073 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7074 Builder.AddTypedTextChunk("atIndexes:");
7075 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7076 Builder.AddPlaceholderChunk("NSIndexSet *");
7077 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7078 Builder.AddTextChunk("indexes");
7079 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7080 CXCursor_ObjCInstanceMethodDecl));
7081 }
7082 }
7083
7084 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7085 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007086 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007087 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007088 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007089 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007090 if (ReturnType.isNull()) {
7091 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7092 Builder.AddTextChunk("void");
7093 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7094 }
7095
7096 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7097 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7098 Builder.AddTextChunk("NSUInteger");
7099 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7100 Builder.AddTextChunk("index");
7101 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7102 CXCursor_ObjCInstanceMethodDecl));
7103 }
7104 }
7105
7106 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7107 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007108 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007109 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007110 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007111 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007112 if (ReturnType.isNull()) {
7113 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7114 Builder.AddTextChunk("void");
7115 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7116 }
7117
7118 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7119 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7120 Builder.AddTextChunk("NSIndexSet *");
7121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7122 Builder.AddTextChunk("indexes");
7123 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7124 CXCursor_ObjCInstanceMethodDecl));
7125 }
7126 }
7127
7128 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7129 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007130 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007131 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007132 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007133 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00007134 &Context.Idents.get("withObject")
7135 };
7136
David Blaikie82e95a32014-11-19 07:49:47 +00007137 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007138 if (ReturnType.isNull()) {
7139 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7140 Builder.AddTextChunk("void");
7141 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7142 }
7143
7144 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7145 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7146 Builder.AddPlaceholderChunk("NSUInteger");
7147 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7148 Builder.AddTextChunk("index");
7149 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7150 Builder.AddTypedTextChunk("withObject:");
7151 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7152 Builder.AddTextChunk("id");
7153 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7154 Builder.AddTextChunk("object");
7155 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7156 CXCursor_ObjCInstanceMethodDecl));
7157 }
7158 }
7159
7160 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7161 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007162 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007163 = (Twine("replace") + UpperKey + "AtIndexes").str();
7164 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00007165 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007166 &Context.Idents.get(SelectorName1),
7167 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00007168 };
7169
David Blaikie82e95a32014-11-19 07:49:47 +00007170 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007171 if (ReturnType.isNull()) {
7172 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7173 Builder.AddTextChunk("void");
7174 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7175 }
7176
7177 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7178 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7179 Builder.AddPlaceholderChunk("NSIndexSet *");
7180 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7181 Builder.AddTextChunk("indexes");
7182 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7183 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7184 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7185 Builder.AddTextChunk("NSArray *");
7186 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7187 Builder.AddTextChunk("array");
7188 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
7189 CXCursor_ObjCInstanceMethodDecl));
7190 }
7191 }
7192
7193 // Unordered getters
7194 // - (NSEnumerator *)enumeratorOfKey
7195 if (IsInstanceMethod &&
7196 (ReturnType.isNull() ||
7197 (ReturnType->isObjCObjectPointerType() &&
7198 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7199 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7200 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007201 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007202 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007203 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7204 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007205 if (ReturnType.isNull()) {
7206 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7207 Builder.AddTextChunk("NSEnumerator *");
7208 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7209 }
7210
7211 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7212 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7213 CXCursor_ObjCInstanceMethodDecl));
7214 }
7215 }
7216
7217 // - (type *)memberOfKey:(type *)object
7218 if (IsInstanceMethod &&
7219 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007220 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007221 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007222 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007223 if (ReturnType.isNull()) {
7224 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7225 Builder.AddPlaceholderChunk("object-type");
7226 Builder.AddTextChunk(" *");
7227 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7228 }
7229
7230 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7231 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7232 if (ReturnType.isNull()) {
7233 Builder.AddPlaceholderChunk("object-type");
7234 Builder.AddTextChunk(" *");
7235 } else {
7236 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007237 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007238 Builder.getAllocator()));
7239 }
7240 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7241 Builder.AddTextChunk("object");
7242 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
7243 CXCursor_ObjCInstanceMethodDecl));
7244 }
7245 }
7246
7247 // Mutable unordered accessors
7248 // - (void)addKeyObject:(type *)object
7249 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007250 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007251 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007252 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007253 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007254 if (ReturnType.isNull()) {
7255 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7256 Builder.AddTextChunk("void");
7257 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7258 }
7259
7260 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7261 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7262 Builder.AddPlaceholderChunk("object-type");
7263 Builder.AddTextChunk(" *");
7264 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7265 Builder.AddTextChunk("object");
7266 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7267 CXCursor_ObjCInstanceMethodDecl));
7268 }
7269 }
7270
7271 // - (void)addKey:(NSSet *)objects
7272 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007273 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007274 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007275 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007276 if (ReturnType.isNull()) {
7277 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7278 Builder.AddTextChunk("void");
7279 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7280 }
7281
7282 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7283 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7284 Builder.AddTextChunk("NSSet *");
7285 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7286 Builder.AddTextChunk("objects");
7287 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7288 CXCursor_ObjCInstanceMethodDecl));
7289 }
7290 }
7291
7292 // - (void)removeKeyObject:(type *)object
7293 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007294 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007295 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007296 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007297 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007298 if (ReturnType.isNull()) {
7299 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7300 Builder.AddTextChunk("void");
7301 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7302 }
7303
7304 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7305 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7306 Builder.AddPlaceholderChunk("object-type");
7307 Builder.AddTextChunk(" *");
7308 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7309 Builder.AddTextChunk("object");
7310 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7311 CXCursor_ObjCInstanceMethodDecl));
7312 }
7313 }
7314
7315 // - (void)removeKey:(NSSet *)objects
7316 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007317 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007318 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007319 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007320 if (ReturnType.isNull()) {
7321 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7322 Builder.AddTextChunk("void");
7323 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7324 }
7325
7326 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7327 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7328 Builder.AddTextChunk("NSSet *");
7329 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7330 Builder.AddTextChunk("objects");
7331 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7332 CXCursor_ObjCInstanceMethodDecl));
7333 }
7334 }
7335
7336 // - (void)intersectKey:(NSSet *)objects
7337 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007338 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007339 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007340 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007341 if (ReturnType.isNull()) {
7342 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7343 Builder.AddTextChunk("void");
7344 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7345 }
7346
7347 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7348 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7349 Builder.AddTextChunk("NSSet *");
7350 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7351 Builder.AddTextChunk("objects");
7352 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
7353 CXCursor_ObjCInstanceMethodDecl));
7354 }
7355 }
7356
7357 // Key-Value Observing
7358 // + (NSSet *)keyPathsForValuesAffectingKey
7359 if (!IsInstanceMethod &&
7360 (ReturnType.isNull() ||
7361 (ReturnType->isObjCObjectPointerType() &&
7362 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
7363 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
7364 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007365 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007366 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007367 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007368 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7369 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007370 if (ReturnType.isNull()) {
7371 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007372 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007373 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7374 }
7375
7376 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7377 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00007378 CXCursor_ObjCClassMethodDecl));
7379 }
7380 }
7381
7382 // + (BOOL)automaticallyNotifiesObserversForKey
7383 if (!IsInstanceMethod &&
7384 (ReturnType.isNull() ||
7385 ReturnType->isIntegerType() ||
7386 ReturnType->isBooleanType())) {
7387 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007388 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007389 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007390 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7391 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007392 if (ReturnType.isNull()) {
7393 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7394 Builder.AddTextChunk("BOOL");
7395 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7396 }
7397
7398 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
7399 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
7400 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007401 }
7402 }
7403}
7404
Alex Lorenzb8740422017-10-24 16:39:37 +00007405void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007406 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007407 // Determine the return type of the method we're declaring, if
7408 // provided.
7409 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007410 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007411 if (CurContext->isObjCContainer()) {
7412 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7413 IDecl = cast<Decl>(OCD);
7414 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007415 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007416 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007417 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007418 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007419 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7420 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007421 IsInImplementation = true;
7422 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007423 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007424 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007425 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007426 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007427 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007428 }
7429
7430 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007431 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007432 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007433 }
7434
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007435 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007436 HandleCodeCompleteResults(this, CodeCompleter,
7437 CodeCompletionContext::CCC_Other,
Craig Topperc3ec1492014-05-26 06:22:03 +00007438 nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007439 return;
7440 }
7441
7442 // Find all of the methods that we could declare/implement here.
7443 KnownMethodsMap KnownMethods;
7444 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007445 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007446
Douglas Gregor636a61e2010-04-07 00:21:17 +00007447 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007448 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007449 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007450 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007451 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007452 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007453 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007454 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7455 MEnd = KnownMethods.end();
7456 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007457 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007458 CodeCompletionBuilder Builder(Results.getAllocator(),
7459 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007460
7461 // Add the '-'/'+' prefix if it wasn't provided yet.
7462 if (!IsInstanceMethod) {
7463 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7464 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7465 }
7466
Douglas Gregor636a61e2010-04-07 00:21:17 +00007467 // If the result type was not already provided, add it to the
7468 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007469 if (ReturnType.isNull()) {
7470 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7471 AttributedType::stripOuterNullability(ResTy);
7472 AddObjCPassingTypeChunk(ResTy,
Alp Toker314cc812014-01-25 16:55:45 +00007473 Method->getObjCDeclQualifier(), Context, Policy,
7474 Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007475 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007476
7477 Selector Sel = Method->getSelector();
7478
7479 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007480 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007481 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007482
7483 // Add parameters to the pattern.
7484 unsigned I = 0;
7485 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
7486 PEnd = Method->param_end();
7487 P != PEnd; (void)++P, ++I) {
7488 // Add the part of the selector name.
7489 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007490 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007491 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007492 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7493 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00007494 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007495 } else
7496 break;
7497
7498 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007499 QualType ParamType;
7500 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7501 ParamType = (*P)->getType();
7502 else
7503 ParamType = (*P)->getOriginalType();
Douglas Gregor9b7b3e92015-07-07 06:20:27 +00007504 ParamType = ParamType.substObjCTypeArgs(Context, {},
7505 ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007506 AttributedType::stripOuterNullability(ParamType);
Douglas Gregor86b42682015-06-19 18:27:52 +00007507 AddObjCPassingTypeChunk(ParamType,
Douglas Gregor29979142012-04-10 18:35:07 +00007508 (*P)->getObjCDeclQualifier(),
7509 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00007510 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007511
7512 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007513 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007514 }
7515
7516 if (Method->isVariadic()) {
7517 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007518 Builder.AddChunk(CodeCompletionString::CK_Comma);
7519 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00007520 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007521
Douglas Gregord37c59d2010-05-28 00:57:46 +00007522 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007523 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007524 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7525 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7526 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007527 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007528 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007529 Builder.AddTextChunk("return");
7530 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7531 Builder.AddPlaceholderChunk("expression");
7532 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007533 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007534 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007535
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007536 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7537 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007538 }
7539
Douglas Gregor416b5752010-08-25 01:08:01 +00007540 unsigned Priority = CCP_CodePattern;
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007541 if (!M->second.getInt())
Douglas Gregor416b5752010-08-25 01:08:01 +00007542 Priority += CCD_InBaseClass;
7543
Douglas Gregor78254c82012-03-27 23:34:16 +00007544 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007545 }
7546
Douglas Gregor669a25a2011-02-17 00:22:45 +00007547 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
7548 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00007549 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007550 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007551 Containers.push_back(SearchDecl);
7552
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007553 VisitedSelectorSet KnownSelectors;
7554 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7555 MEnd = KnownMethods.end();
7556 M != MEnd; ++M)
7557 KnownSelectors.insert(M->first);
7558
7559
Douglas Gregor669a25a2011-02-17 00:22:45 +00007560 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7561 if (!IFace)
7562 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7563 IFace = Category->getClassInterface();
7564
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007565 if (IFace)
7566 for (auto *Cat : IFace->visible_categories())
7567 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007568
7569 if (IsInstanceMethod) {
7570 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7571 for (auto *P : Containers[I]->instance_properties())
7572 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7573 KnownSelectors, Results);
7574 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007575 }
7576
Douglas Gregor636a61e2010-04-07 00:21:17 +00007577 Results.ExitScope();
7578
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007579 HandleCodeCompleteResults(this, CodeCompleter,
7580 CodeCompletionContext::CCC_Other,
7581 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007582}
Douglas Gregor95887f92010-07-08 23:20:03 +00007583
7584void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7585 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00007586 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00007587 ParsedType ReturnTy,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007588 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007589 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007590 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007591 if (ExternalSource) {
7592 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7593 I != N; ++I) {
7594 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007595 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007596 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007597
7598 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007599 }
7600 }
7601
7602 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007603 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007604 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007605 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007606 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00007607
7608 if (ReturnTy)
7609 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007610
Douglas Gregor95887f92010-07-08 23:20:03 +00007611 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007612 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7613 MEnd = MethodPool.end();
7614 M != MEnd; ++M) {
7615 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7616 &M->second.second;
Nico Weber2e0c8f72014-12-27 03:58:08 +00007617 MethList && MethList->getMethod();
Argyrios Kyrtzidisd3da6e02013-04-17 00:08:58 +00007618 MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007619 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007620 continue;
7621
Douglas Gregor45879692010-07-08 23:37:41 +00007622 if (AtParameterName) {
7623 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007624 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007625 if (NumSelIdents &&
7626 NumSelIdents <= MethList->getMethod()->param_size()) {
7627 ParmVarDecl *Param =
7628 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007629 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007630 CodeCompletionBuilder Builder(Results.getAllocator(),
7631 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007632 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007633 Param->getIdentifier()->getName()));
7634 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007635 }
7636 }
7637
7638 continue;
7639 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007640
Nico Weber2e0c8f72014-12-27 03:58:08 +00007641 Result R(MethList->getMethod(),
7642 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007643 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007644 R.AllParametersAreInformative = false;
7645 R.DeclaringEntity = true;
7646 Results.MaybeAddResult(R, CurContext);
7647 }
7648 }
7649
7650 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007651
7652 if (!AtParameterName && !SelIdents.empty() &&
7653 SelIdents.front()->getName().startswith("init")) {
7654 for (const auto &M : PP.macros()) {
7655 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7656 continue;
7657 Results.EnterNewScope();
7658 CodeCompletionBuilder Builder(Results.getAllocator(),
7659 Results.getCodeCompletionTUInfo());
7660 Builder.AddTypedTextChunk(
7661 Builder.getAllocator().CopyString(M.first->getName()));
7662 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7663 CXCursor_MacroDefinition));
7664 Results.ExitScope();
7665 }
7666 }
7667
Douglas Gregor00c37ef2010-08-11 21:23:17 +00007668 HandleCodeCompleteResults(this, CodeCompleter,
7669 CodeCompletionContext::CCC_Other,
7670 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007671}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007672
Douglas Gregorec00a262010-08-24 22:20:20 +00007673void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007674 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007675 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007676 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007677 Results.EnterNewScope();
7678
7679 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007680 CodeCompletionBuilder Builder(Results.getAllocator(),
7681 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007682 Builder.AddTypedTextChunk("if");
7683 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7684 Builder.AddPlaceholderChunk("condition");
7685 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007686
7687 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007688 Builder.AddTypedTextChunk("ifdef");
7689 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7690 Builder.AddPlaceholderChunk("macro");
7691 Results.AddResult(Builder.TakeString());
7692
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007693 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007694 Builder.AddTypedTextChunk("ifndef");
7695 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7696 Builder.AddPlaceholderChunk("macro");
7697 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007698
7699 if (InConditional) {
7700 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007701 Builder.AddTypedTextChunk("elif");
7702 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7703 Builder.AddPlaceholderChunk("condition");
7704 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007705
7706 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007707 Builder.AddTypedTextChunk("else");
7708 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007709
7710 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007711 Builder.AddTypedTextChunk("endif");
7712 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007713 }
7714
7715 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007716 Builder.AddTypedTextChunk("include");
7717 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7718 Builder.AddTextChunk("\"");
7719 Builder.AddPlaceholderChunk("header");
7720 Builder.AddTextChunk("\"");
7721 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007722
7723 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007724 Builder.AddTypedTextChunk("include");
7725 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7726 Builder.AddTextChunk("<");
7727 Builder.AddPlaceholderChunk("header");
7728 Builder.AddTextChunk(">");
7729 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007730
7731 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007732 Builder.AddTypedTextChunk("define");
7733 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7734 Builder.AddPlaceholderChunk("macro");
7735 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007736
7737 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007738 Builder.AddTypedTextChunk("define");
7739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7740 Builder.AddPlaceholderChunk("macro");
7741 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7742 Builder.AddPlaceholderChunk("args");
7743 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7744 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007745
7746 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007747 Builder.AddTypedTextChunk("undef");
7748 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7749 Builder.AddPlaceholderChunk("macro");
7750 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007751
7752 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007753 Builder.AddTypedTextChunk("line");
7754 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7755 Builder.AddPlaceholderChunk("number");
7756 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007757
7758 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007759 Builder.AddTypedTextChunk("line");
7760 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7761 Builder.AddPlaceholderChunk("number");
7762 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7763 Builder.AddTextChunk("\"");
7764 Builder.AddPlaceholderChunk("filename");
7765 Builder.AddTextChunk("\"");
7766 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007767
7768 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007769 Builder.AddTypedTextChunk("error");
7770 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7771 Builder.AddPlaceholderChunk("message");
7772 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007773
7774 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007775 Builder.AddTypedTextChunk("pragma");
7776 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7777 Builder.AddPlaceholderChunk("arguments");
7778 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007779
David Blaikiebbafb8a2012-03-11 07:00:24 +00007780 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007781 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007782 Builder.AddTypedTextChunk("import");
7783 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7784 Builder.AddTextChunk("\"");
7785 Builder.AddPlaceholderChunk("header");
7786 Builder.AddTextChunk("\"");
7787 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007788
7789 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007790 Builder.AddTypedTextChunk("import");
7791 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7792 Builder.AddTextChunk("<");
7793 Builder.AddPlaceholderChunk("header");
7794 Builder.AddTextChunk(">");
7795 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007796 }
7797
7798 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007799 Builder.AddTypedTextChunk("include_next");
7800 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7801 Builder.AddTextChunk("\"");
7802 Builder.AddPlaceholderChunk("header");
7803 Builder.AddTextChunk("\"");
7804 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007805
7806 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007807 Builder.AddTypedTextChunk("include_next");
7808 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7809 Builder.AddTextChunk("<");
7810 Builder.AddPlaceholderChunk("header");
7811 Builder.AddTextChunk(">");
7812 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007813
7814 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007815 Builder.AddTypedTextChunk("warning");
7816 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7817 Builder.AddPlaceholderChunk("message");
7818 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007819
7820 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7821 // completions for them. And __include_macros is a Clang-internal extension
7822 // that we don't want to encourage anyone to use.
7823
7824 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7825 Results.ExitScope();
7826
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007827 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007828 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007829 Results.data(), Results.size());
7830}
7831
7832void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007833 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007834 S->getFnParent()? Sema::PCC_RecoveryInFunction
7835 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007836}
7837
Douglas Gregorec00a262010-08-24 22:20:20 +00007838void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007839 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007840 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007841 IsDefinition? CodeCompletionContext::CCC_MacroName
7842 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007843 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7844 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007845 CodeCompletionBuilder Builder(Results.getAllocator(),
7846 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007847 Results.EnterNewScope();
7848 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7849 MEnd = PP.macro_end();
7850 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007851 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007852 M->first->getName()));
Argyrios Kyrtzidis5c8b1cd2012-09-27 00:24:09 +00007853 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7854 CCP_CodePattern,
7855 CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00007856 }
7857 Results.ExitScope();
7858 } else if (IsDefinition) {
7859 // FIXME: Can we detect when the user just wrote an include guard above?
7860 }
7861
Douglas Gregor0ac41382010-09-23 23:01:17 +00007862 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007863 Results.data(), Results.size());
7864}
7865
Douglas Gregorec00a262010-08-24 22:20:20 +00007866void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007867 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007868 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007869 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007870
7871 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007872 AddMacroResults(PP, Results, true);
Douglas Gregorec00a262010-08-24 22:20:20 +00007873
7874 // defined (<macro>)
7875 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007876 CodeCompletionBuilder Builder(Results.getAllocator(),
7877 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007878 Builder.AddTypedTextChunk("defined");
7879 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7880 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7881 Builder.AddPlaceholderChunk("macro");
7882 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7883 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007884 Results.ExitScope();
7885
7886 HandleCodeCompleteResults(this, CodeCompleter,
7887 CodeCompletionContext::CCC_PreprocessorExpression,
7888 Results.data(), Results.size());
7889}
7890
7891void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7892 IdentifierInfo *Macro,
7893 MacroInfo *MacroInfo,
7894 unsigned Argument) {
7895 // FIXME: In the future, we could provide "overload" results, much like we
7896 // do for function calls.
7897
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007898 // Now just ignore this. There will be another code-completion callback
7899 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007900}
7901
Douglas Gregor11583702010-08-25 17:04:25 +00007902void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007903 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007904 CodeCompletionContext::CCC_NaturalLanguage,
Craig Topperc3ec1492014-05-26 06:22:03 +00007905 nullptr, 0);
Douglas Gregor11583702010-08-25 17:04:25 +00007906}
7907
Alex Lorenzf7f6f822017-05-09 16:05:04 +00007908void Sema::CodeCompleteAvailabilityPlatformName() {
7909 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
7910 CodeCompleter->getCodeCompletionTUInfo(),
7911 CodeCompletionContext::CCC_Other);
7912 Results.EnterNewScope();
7913 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
7914 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
7915 Results.AddResult(CodeCompletionResult(Platform));
7916 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
7917 Twine(Platform) + "ApplicationExtension")));
7918 }
7919 Results.ExitScope();
7920 HandleCodeCompleteResults(this, CodeCompleter,
7921 CodeCompletionContext::CCC_Other, Results.data(),
7922 Results.size());
7923}
7924
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007925void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007926 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007927 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007928 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7929 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007930 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7931 CodeCompletionDeclConsumer Consumer(Builder,
7932 Context.getTranslationUnitDecl());
7933 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7934 Consumer);
7935 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007936
7937 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor8cb17462012-10-09 16:01:50 +00007938 AddMacroResults(PP, Builder, true);
Douglas Gregorb14904c2010-08-13 22:48:40 +00007939
7940 Results.clear();
7941 Results.insert(Results.end(),
7942 Builder.data(), Builder.data() + Builder.size());
7943}